我有一个 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 比 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 header 中的标志和字段。发送一个至少需要一个 header 的带宽,加上较低层的带宽。但是数据段已经包含了所有这些……所以如果您要发送数据,您可以免费同时发送一个 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 之上的应用层协议(protocol)将有一些协议(protocol)特定的方式来确认发送和接收的数据。
关于networking - TCP 是在每个数据包上发送 SYN/ACK 还是仅在第一个连接上发送?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3604485/