一、关于滑动窗口协议
在TCP协议中,所有的SEQ包发送出去都必须要受到对方的ACK才认为是发送成功,如果长时间没有收到ACK回复确认,发送方需要重新发送该包。而如果发送方每次都是发送一个包,然后等到接收方回复ACK了再发送下一个包,那么数据包的传输效率就相当低了。滑动窗口协议的作用就是为了解决这个问题。
在滑动窗口协议中,发送方可以同时发送多个数据包并可以不用等待接收方确认,这样就大大增加了网络的推图两。唯一的限制是:接收方未确认的数据包不得超过双方约定的窗口个数。TCP包头中有一个两字节的字段表示滑动窗口的大小,因此最大的滑动窗口大小为65535,这个大小是由接收方提出的,以接收方的大小为准。
最大窗口65536并不是绝对的,TCP选项中有提供一个窗口放大的选项可以对这个数值缩放。
例如以下数据,将发送的字节从1至11进行标号,接收方提出的窗口大小为6,此时已发送的1/2/3字节数据被接收方确认,当前窗口覆盖了从第4字节到第9字节的区域。4/5/6字节是已经发送但是还未收到确认,此时发送方还可以发送的数据域只剩下三个,即7/8/9三个数据。当7/8/9发送完成后,发送方无法再继续发送数据。只有接收方再确认序号4的数据后,发送方才能继续发送数据10。此时可用的窗口将会向右延伸到10,同时左边已发送并确认的数据也会向右延伸到4。
这个过程看起来就像是一个窗口不停向右滑动,因此该协议被称为滑动窗口协议。
滑动窗口涉及到以下几个概念:
- 窗口合拢:当窗口左边界向右靠近时,这种现象发生在数据被发送方确认时。
- 窗口张开:窗口的右边界向右移动的时候,这种现象发生在接收端处理的数据的时候。
- 窗口收缩:窗口右边界向左移动时,这种现象不常发生。
注意:窗口大小是由接收方通告的,通过采取慢启动和拥塞避免算法等机制来使带宽和性能取得最佳。
二、坚持定时器
2.1 坚持定时器的引入
思考以下场景:接收方的接收缓冲区已满,因此接收方发送了一个窗口大小为0的数据到发送方,此时发送方停止发送数据。经过一段时间后,接收方有空闲的缓冲区可以接收数据,此时给发送方发了一个窗口大小不为0的包,但是恰巧这个包在路上出现了意外没有到达发送方。此时发送方还在一直等待接收方发送不为0的窗口过来,但是接收方又在等待发送方继续发送数据。两者相当于发生了死锁。
2.2 工作原理
为了解决上面这个问题,TCP引入了坚持定时器,该定时器功能为:TCP连接的一方收到对方窗口为0的通知时,启动该定时器,若定时器持续时间到达后还没有收到对方窗口大小不为0的通知,主动发送一个零窗口探测包(仅携带1字节数据),对方则需要在这个包中回复当前窗口的大小。
三、关于window scale选项
window scale
选项是提供给滑动窗口协议用于对窗口大小放大使用,在SYN
包或者SYN,ACK
包中作为选项字段,表示滑动窗口的实际大小要根据这个值来进行缩放(SYN包本身的窗口不会缩放)。
发送方和接收方的滑动窗口缩放因子大小可以不一样,两者互不干扰,但实际上窗口大小还是以接收方为准。使用wireshark抓包很容易就能看到这个缩放选项,以下是一个数据包示例。
这个包是客户端发起的三次握手数据包:
客户端设置了窗口缩放大小为256
,因此后面实际计算的时候窗口大小要乘以这个缩放大小1025
(使用wireshark很容日就能看到),乘以256后得到实际的窗口大小为262400
:
Calculated window size: wireshark根据缩放因子计算出来的实际窗口大小。
Window size scaling factor: 窗口缩放因子。
这两个参数都是wireshark自动生成的,并不是携带在TCP包中的字段。
评论