当前位置: 首页 > Linux

再说说TCP的重传退避和公平性

时间:2023-04-07 01:01:48 Linux

TCP发送消息,如果没有收到对端的回应,会在重传定时器超时后触发重传,超时时间遵循二进制退避原则,即,{1,2,4,8,16}这会使超时时间加倍。Backoff是因为TCP认为丢包就意味着网络拥塞。为了不加剧网络拥塞,TCP选择等待更长的时间再重传。这与CSMA/CD中的二进制退避算法完全相同。网络拥塞的根源在链接中已经提到。网络中的网络设备(路由器、交换机)收到超过队列限制的消息后,后续消息将被丢弃。从TCP采用的二进制退避算法来看,TCP绝对是网络中的谦虚君子。它遵守的规则是:既然已经被屏蔽了,我等一会再发。如果还是堵,我等两倍的时间!对于整个网络来说,这确实是一个很好的减负方式。要知道当发送窗口满时,指数退避一次意味着单位时间内发送的包数变成原来的1/2,而一旦退避,就只有原来的1/4了!就像一辆有限行程的汽车。奇数和偶数限制不好用。我规定一辆车只能开4天1天……可是,TCP真的需要这样约束自己吗?,换句话说,为什么TCP要用x2后退?重传定时器超时时间不能线性增加(每次增加X秒),或者乘以一个更小的系数(比如x1.5)吗?我们可以从CSMA/CD中找到灵感。CSMA/CD使用x2的原因很容易理解。共享介质中的每个节点都不知道还有多少其他节点。使用x2backoff就是利用二分法快速找到一个能让整个系统稳定运行的时隙分配方案!例如,假设系统中有4个节点的发包速率相同,那么最终的稳定分配方案自然是将一段时间分成4份,每个节点占用1个时隙。如果此时添加4个相同的节点。那么很明显,8个节点都会发包去冲突。怎样才能不冲突?当然分配给每个节点的时间就减少了一半!当然,这里给出的示例节点都是2的整数次方,如果不是怎么办?此时二元退避仍然可以很快达到稳定。可能此时的时隙分配方案并不是最合理的,但是正如上面所说,每个节点都不知道还有多少其他节点。对于单个节点,二进制退避是找到使每个节点正常工作的解决方案的最快方法!二进制退避方案隐含了公平性的考虑,这是从整个网络的角度,而不是从其中一台主机的角度!但是对于特定的主机来说,不遵守这个退避规则显然更有利……比如使用一个固定的重传定时器时间。在这种网络中,没有拥塞时每个人都是安全的。一旦发生拥塞,不退避的主机理论上可以发送更多的包!当然,这似乎是以其他遵守规则的主机为代价的,它们的重传会增加。那么,如果每个人都不遵守怎么办?结果就是大家的重传次数都增加了,拥塞比大家的合规还要严重,因为网络上的设备丢包多了!这有点像囚徒困境。别人避开你,你不退,你就可以赚到钱。如果别人避开你,你也避开它,那么你就会受苦。如果每个人都不服从,那还不如全部服从。。。。。当然,现实中的网络和CSMA/CD中的共享介质是不一样的。一个简单的区别就是在CSMA/CD中,如果一个节点检测到信道忙,它是否发送数据?需要等待;在网络中,没有这样的共享介质,路由器缓冲队列,所以两台主机仍然可以发送消息。话说回来,很多游戏为了保证实时性,是不会选择TCP的!毕竟TCP太无私了,它是为整个网络考虑的。实时游戏需要什么!快速地!那么,如果他们需要可靠的运输怎么办?很简单,就是用UDP,然后在用户态做ARQ。想怎么弄就怎么弄,比如KCP就是这么个东西。