我想知道 TCP 究竟是如何实现按顺序交付的。
可以说这是事件列表
- 已发送数据包1,已收到确认。
- packet2 已发送,确认未收到。
- 数据包 3 发送。
- 数据包 4 发送。
- 收到 ack4。
- 收到 ack3。
- 收到 ack2。
你能向我描述一下顺序发生的事情吗?
简短的回答是每个数据包都包含偏移信息(伪装成序列号),指定其有效负载在流中的位置。
假设发生以下情况:收到数据包 1,未收到数据包 2,收到数据包 3 和数据包 4。此时接收 TCP 堆栈知道将数据包 3 和 4 的内容复制到缓冲区的何处,并且它知道它还没有收到先前的数据,因此它将使数据包 1 的数据可供读取,但不会使数据包 3 或 4 数据可用,直到收到数据包 2。
传输 TCP 堆栈通常不会在发送下一个数据包之前等待任何单个数据包的确认,但如果它没有收到给定数据包的确认(并且 ACK 可以并且为了效率而捆绑在一个数据包中),它将重新传输它,直到收到 ACK。
事件的确切顺序取决于网络条件、TCP 堆栈实现、选择的 TCP 策略、套接字选项和其他因素。
TCP 数据包具有序列号(自开始以来的字节偏移量,来自内存),并且 ACK 消息确认已收到特定偏移量:
因此,您最终可能会遇到以下情况:
data 1 (10 bytes) ->
<- ack (10, data1)
data 2 (15 bytes) ->
data 3 (10 bytes) ->
data 4 ( 8 bytes) ->
<- ack (25, data1/2/3)
<- ack (33, data1/2/3/4)
换句话说,发送方可以继续发送而不管确认是否已满,直到其缓冲区已满(它必须保留未确认的数据包以防它需要重新传输它们)。
发送和确认之间的这种“断开”可以大大加快数据流。
在接收端,数据包可能会乱序到达,并且会一直保留它们,直到可以将某些东西按顺序传递到更高级别。
例如,如果data 3
之前到达data 2
,接收端会一直持有直到data 2
到达,然后它们都将被向上发送。