由于网络存在延迟丢包、接收端处理数据与发送端发送数据的速度有差别以及接收端可能采取收到多个包以后才统一回复Ack的策略,那么发送端就需要保存“已发送但未收到Ack”的数据列表,当触发重传时,直接在该链表中找到相应需要重传的数据,重传给接收端。
在文章《【技术】TCP 的那些事 | 滑动窗口 》中讲述了滑动窗口的基本原理,其中“从发送端看发送数据的状态”中的Category2:已发送但未收到Ack的数据,也即“Byte in flight”,对应中文也即“在途字节数”,如图1所示。

图1 发送端发送队列
从定义看,在途字节数 = 已发送数据-已收到Ack的数据
已发送数据可以通过发送端的Seq确定,已收到Ack的数据可以通过发送端接收到接收端回复的Ack确定。
那么,如何计算在途字节数呢?
从抓包的角度更容易理解其计算过程,图2为一张Wireshark的抓包截图:

图2 Wireshark抓包
对于443 <--> 56216 的数据交互,从443-->56216的1号报文,其Ack为122402948,而12号报文56216 -->443的报文的Seq为122417468,其Len为1452,那么在途字节数为122417468 + 1452 - 122402948= 15972(为方便讲解,特意取了12号报文,其他报文也可)。其中122417468 + 1452表示已发送数据(Seq + Len),122402948表示Ack。
那么在途字节数 = Seq + Len - Ack
其中,Seq为发送方本次发送数据的Seq,Len为发送方本次发送数据的Len,Ack为接收方最近一次回复报文的Ack。
参考资料
1. 《Wireshark网络分析的艺术》
2. 《The TCP/IP Guide》

824

被折叠的 条评论
为什么被折叠?



