我有一个TCP服务器,它侦听传入的客户端,然后每秒向它发送一个数据包.我想知道,SYN/ACK数据包是否仅在初始连接时发送,所以它看起来像这样:
SYN ACK DATA DATA DATA
或者它是否与每个数据包一起发送,像这样?
SYN ACK DATA SYN ACK DATA SYN ACK DATA
此外,如果是第一种情况,如果您只是长时间保持连接打开,那么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,因此通信是单向的,不保证传送,并且不保留顺序.但它具有较少的开销,因此当速度比可靠性更重要时,例如在流媒体中,它是有用的.
这有点简化,但它是我现在能做的最好的.
关于TCP的wikipedia条目以及RFC当然还有更多内容.