TCP是在每个数据包上发送SYN / ACK还是仅在第一个连接上发送?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了TCP是在每个数据包上发送SYN / ACK还是仅在第一个连接上发送?相关的知识,希望对你有一定的参考价值。

我有一个TCP服务器,它侦听传入的客户端,然后每秒向它发送一个数据包。我想知道,SYN / ACK数据包是否仅在初始连接时发送,所以它看起来像这样:

<client connect>
SYN
ACK
DATA
DATA
DATA
<client disconnect>

或者它是否与每个数据包一起发送,像这样?

<client connect>
SYN
ACK
DATA

SYN
ACK
DATA

SYN
ACK
DATA
<client disconnect>

此外,如果是第一种情况,如果您只是长时间保持连接打开,那么UDP over TCP是否有任何好处?

答案

它有点像:

+-------------------------------------------------------+
|     client           network            server        |
+-----------------+                +--------------------|
|    (connect)    | ---- SYN ----> |                    |
|                 | <-- SYN,ACK -- |     (accepted)     |
|   (connected)   | ---- ACK ----> |                    |
\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/

when client sends...
\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/
|                 |                |                    |
|     (send)      | ---- data ---> |                    |
|                 | <---- ACK ---- |  (data received)   |
\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/

when server sends...
\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/
|                 |                |                    |
|                 | <--- data ---- |       (send)       |
| (data received) | ---- ACK ----> |                    |
\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/

...and so on, til the connection is shut down or reset

SYN开始连接;你通常只在连接建立时才能看到它。但是通过TCP发送的所有数据都需要ACK。必须考虑发送的每个字节,否则将重新发送(或在重度情况下重置连接(关闭))。

实际连接通常不完全如上图所示,原因有两个:

  • ACK可以建立起来,因此一个ACK可以确认到目前为止收到的所有内容。这意味着您可以使用一个ACK确认两个或多个发送。
  • ACK只是TCP头中的标志和字段。发送一个至少需要一个标头的带宽,加上较低层的粘性。但是数据段已经包含了所有......因此,如果您要发送数据,您可以同时免费发送ACK。

大多数TCP / IP堆栈尝试减少裸ACK的数量,而不会过度冒重传或连接重置的风险。所以像这样的对话很有可能:

\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/
|                 |                |                    |
|                 | <--- data ---- |       (send)       |
| (data received) |                |                    |
|     (send)      | -- data,ACK -> |                    |
|                 |                |  (data received)   |
|                 | <- data,ACK -- |       (send)       |
| (data received) |                |                    |
|  (wait a bit)   | <--- data ---- |       (send)       |
| (data received) |                |                    |
|     (send)      | -- data,ACK -> |                    |
|                 |                |  (data received)   |
|     (send)      | ---- data ---> |   (wait a bit)     |
|                 |                |  (data received)   |
|                 | <- data,ACK -- |       (send)       |
| (data received) |                |                    |
|  (wait a bit)   |   (dead air)   |                    |
|                 | ---- ACK ----> |                    |
\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/\_/

至于UDP,没有内置的SYN和ACK概念 - UDP本质上是“不可靠的”,而不是面向连接的,因此这些概念并不适用。您的确认通常只是服务器的响应。但是,在UDP之上构建的一些应用层协议将具有一些特定于协议的确认发送和接收数据的方式。

另一答案

SYN仅在开始时。

ACK在任一方向上的后续段上。 [edit] ACK还将定义窗口大小。例如,如果窗口大小为100,则发送方可以在期望接收ACK之前发送100个段。例如,如果发送者发送100个段但段号50丢失,则接收者将获得1-49和51 -100。接收器然后将确认50(它预期的下一个段)并将窗口大小设置为1.发送器将重新发送序列号为50的1个段。接收器然后将确认101并将窗口大小设置回更高的数字[编辑]

两者实际上都是TCP头中的字段,并且可以与数据一起发送,尽管SYN和第一个ACK通常是无数据的。

所以你描述的场景都不是很正确。第一个实际上更接近现实,但SYN之后的所有数据包都必须包括ACK,还有一个确认号字段,用于标识预期的下一个数据包的数量。

会话结束还涉及握手FIN标记的数据包和与之相关的ACK。

交换的序列号用于识别丢失的分组并启用重试机制,并且还以正确的顺序重新组装整个分组流。

此外,如果是第一种情况,如果您只是长时间保持连接打开,那么UDP over TCP是否有任何好处?

使用UDP,您不仅可以在很长一段时间内保持连接打开状态。没有联系。

这个SYN / ACK / FIN标志序列是连接的原因。

使用UDP时,没有SYN或ACK,因此通信是单向的,不保证传送,并且不保留顺序。但它具有较少的开销,因此当速度比可靠性更重要时,例如在流媒体中,它是有用的。

这有点简化,但它是我现在能做的最好的。

wikipedia entry on TCP,当然还有RFC中,有更多内容。

另一答案

想象一下:原始的TCP标准RFC 793允许数据与第一个SYN数据包一起发送。但是,今天情况并非如此。在从连接请求者发起三方握手期间,您得到的是一个单独的SYN数据包。假设A请求与B连接,因此A发送一个SYN位设置的数据包。 B以ACK响应以确认接收并发送A ACK + SYN分组。然后可以传输数据。

Dordal has a very good explanation on this matter. Click this link here.

以上是关于TCP是在每个数据包上发送SYN / ACK还是仅在第一个连接上发送?的主要内容,如果未能解决你的问题,请参考以下文章

TCP3次握手和4次挥手及其为什么

重温TCP

关于TCP建立连接

TCP是长久连接吗?

浅析TCP

TCP 三次握手(SYN,SYN-ACK,ACK)