window size流控过程
- TCP是以数据段的形式传输数据的,一个数据段包含很多个字节,相当于批量传输
- 为避免大量数据淹没接收方,采用流控技术,利用的是段头中的一个字段叫窗口尺寸(window size)
一个简单例子
从上往下过程:
- sender发送了一个2K的数据,因为SEQ=0,所以这个2K的字节编号是从0一直到2047
- 这个数据到达receiver之后receiver的内存就被占据了一半,还剩下2K,所以这个接收方会回发一个确认:ACK=2048,WIN=2048,分别表示(累计)确认和剩下空间的大小
- sender再次发送了一个2K的数据,接收方的缓存全部被充满,会发确认:ACK=4096,WIN=0
- 过一段时间接收方对缓存里面的数据进行了处理,从而空出了2K的空间,于是它马上发送了一个更新窗口,当然,这个更新窗口数据段里面WIN=2048,而中间因为没有再接受数据所以ACK=4096不变……
别忘了TCP传输是双工的,也就是说sender/receiver可以交换,它们可以互为收发方
一些发送策略:
- 当窗口数为0时发送者不能正常发送数据段,除非发送紧急(Urgent)数据(例如用户想杀掉远端机器上的进程的时候)
- 发送者可以发送一个字节的数据段,以便让接收者再次发送期待接收的字节号和窗口数(避免死锁)
- 发送者不需要马上发送应用程序产生的数据,接收者也不需要马上发送应答(当收到数据的时候)
接收方/发送方的优化
远程交互telnet的最坏情形图示:
优化方法:接收端可以推迟500ms发送确认分组和窗口更新窗口,以便可以免费搭载在处理后的回显分组内(free ride)
发送端优化Nagle算法
- 当数据以一次一字节的速度到达的时候,只发送第一个字节,然后将后续的字节缓存起来,直到发出的字节得到确认
- 将缓存起来的字节在一个数据段中发出,再继续缓存,直到发出的数据得到确认
- Nagle算法在很多TCP上实现,但是有些时候最好禁用,例如当一个X-Windows应用在互联网运行的时候,鼠标的移动事件必须发送给远程计算机,把这些移动事件收集起来一批一批发送出去,使得鼠标的移动极不连贯
傻瓜窗口综合症
有大块数据被传递给发送端TCP实体,然而接收端的交互式应用每次只读取一个字节的时候,如下
Clark解决方案 :阻止接收方发送只有1个字节的窗口更新,它必须等待一段时间,当有了一定数量的空间之后再告诉发送方
总结