最完整,原始的拥塞避免算法描述可以查找[Jacobson 1988] 这个论文文档。
这个算法是为了处理在连接双方的某个中间节点发生了拥塞,比如在一个处理能力相对较弱的路由器上,当收到的报文超过了它处理能力允许的最大缓存队列个数时,它就会丢弃一些报文,或许是后续收到的,或许是队列中的某些,根据不同的实现需求来丢弃相应的报文。
在TCP协议层面上判断一个网络连接出现拥塞有:
1.当一个等待确认ACK定时器超时,
2.当收到了一个重复的确认ACK。
当然这些并不一定都是由网络拥塞引起的,比如收到一个重复的ack,这个也有可能是因为一个乱序报文的ack导致的,但是这两个标记都表明了连接双方的网络出现了问题,这时的TCP应该要能够处理这样的问题。
在TCP中拥塞避免算法和慢启动算法是两个目的不同的,独立的算法,但是当拥塞发生时,tcp会降低分组进入网络的传输速率,这个时候就可以使用慢启动算法来做到这一点,在实际中这两个算法通常是一起实现的。
拥塞算法和慢启动需要为每个连接维护两个变量:一个拥塞窗口cwnd(这里计数的是以MSS为单位,比如拥塞窗口为1,即此时允许发送一个报文,报文大小是一个MSS字节)和一个慢启动门限ssthresh。
处理过程:
1.对一个给定的连接初始化上述的两个变量cwnd= 1和ssthresh为65535字节(貌似是一个基本的最大缓存大小,当然缓存后续可以通过选项变得更大以满足高速率带宽的网络)
2.TCP每次发送的报文不能超过cwnd和接收方通告窗口大小(window或许每次都会有变化)。拥塞避免是发送方的流量控制,而通过窗口则是接收方进行的流量控制(来达到适合自己处理能力的流量)。
前面两个步骤是在每个连接中都会有的处理过程(当然要启用慢启动和拥塞避免算法)。
3.发生拥塞时(收到重复ACK或者发生超时),ssthresh会被重新赋值为当前窗口大小的一半(准确的是cwnd和接收方通过窗口最小值的一半,但是最小不能小于2个报文段来)。此外,如果是超时引起了拥塞,则cwnd被设置为一个报文段(这里就是慢启动开始)。
4.当新的重传数据被接收方确认时,就增加cwnd,当增加的幅度区别于我们现在是使用慢启动还是拥塞避免。这里如果cwnd小于或者等于ssthresh时则使用的是慢启动(这个时候是按照指数级递增的),反之则使用的是拥塞避免。(慢启动一直持续到我们发生拥塞时记录的窗口一半的时候才停止,这个时候开始了拥塞避免)。
这里详细说明一下慢启动的cwnd的增加和拥塞避免时cwnd的增加。
慢启动,当发送了cwnd = 1时,收到接收方的确认后,这个时候cwnd = 2,即发送方可以发送 2个报文,当这两个报文的确认都收到时(这里有个疑问,因为接收方发送确认并不是和发送的报文一一对应的,这里怎么确认分别收到了上述发出的两个报文的确认,还是说只要ack能反应是对这两个报文的确认就可以了),发送方就可以就可以发送2个报文,然后是4个,8个...呈现2的指数增加。
拥塞避免,在开始执行拥塞算法时(即此时cwnd是刚开始大于ssthresh),每次收到接收方的确认的时候cwnd增加1/cwnd个大小,并且在一个RTT(一个报文发送到接收到ack的周期)之间最多只能为cwnd增加1,就是说不管接收到多少个ack都不会想慢启动那样指数的增加。
阅读(3742) | 评论(0) | 转发(1) |