以下内容总结至 TCP/IP 详解 卷一,因为看的是英文版,所以用了很多英文单词:
1.背景知识:
TCP以发送但未被确认的数据总量不超过MIN(发送方的cwnd,接收方的win),也就是发送到外部网络的所有未被确认的segment大小是受限的。
术语:
seg.size:一个segment 的字节大小
cwnd:congestion window
ssthresh:slow start threshold
下面的总结的基本假设条件:
数据发送方的cwnd 一直比 接收方的win小。
congestion 分两种情况:
1.已发送但未确认的segment等待超时
2.收到4个相同的ACK(第一个是正常的segment确认,后三个是segment lost后,接收方收到out of order的segment而发送的ACK)
发生以上两种情况,TCP就认为网络堵塞了,对于第一种情况,采用slow start 和congestion avoidance ,对第二种情况采用fast retransmit和fast recovery(重要,刚开始看书时没有理解这一点)。
2. ssthresh & cwnd
ssthresh 是slow start 的阈值,TCP会根据不同的传输状态修改cwnd和ssthresh的值,从而导致执行slow start 或者congestion avoidance。ssthresh最小为2 * seg.size。而且不管ssthresh怎么变化,都等于seg.size的倍数,如果不等,就向下取整。
2.1 ssthresh 变化条件
1. TCP连接建立时,ssthresh 初始化为65535 bytes。
2.congetion发生时(包括两种情况),ssthresh = MIN(cwnd,win)/ 2,小于小于2*seg.size。
2.2 cwnd变化条件
1.初始化为seg.size
2.发生第一种congestion(见第一节)。cwnd = seg.size
3.发生第二种congetion。cwnd = MIN(原cwnd, win)/ 2 + 3 * seg.size。这时候并不执行congetion avoidance,而是执行fast recovery。
3. slow start :
3.1 开始条件:
cwnd 小于 ssthresh。
3.2 slow start algorithm
每收到一个正常的ACK(重复的ACK不算),cwnd就增加1 seg.size。如下:
1.cwnd = 1*seg.size. send 1 segment (SN: 1) 此时在外部网络未被确认的segment有:1
2. recv 1 ACK(SN:2), cwnd = 2*seg.size ,send 2 segment ( SN: 2, 3) 此时在外部网络未被确认的segment有:2, 3
3.recv 1 ACK(SN:3), cwnd = 3*seg.size , send 3 segment (SN:4, 5,) 此时在外部网络未被确认的segment有:4, 5 ,6
......
可以看到,在外部网络的segment 总size是同cwnd保持一致的。而且cwnd 是以2次幂增长的,上面的示例看着不像。但是这样看就明白了:
1. send 1 个seg ,ack 1 个 seg,cwnd <- cwnd + 1 *seg.size
2. send 2 个seg ,ack 2个 seg,cwnd <- cwnd + 2*seg.size
2. send 4 个seg ,ack 4 个 seg,cwnd <- cwnd + 4*seg.size
3.3 slow start 的结束条件:
cwnd 大于 ssthresh, slow start 就会结束。
4. congestion avoidance:
4.1开始条件:
cwnd 大于ssthresh 就会进入。
4.2 congsetion avoidance algorithm
每收到一个ACK,cwnd就增加 seg.size / cwnd 个 seg.size的大小。比如seg.size = 256, cwnd = 768 , 那新的cwnd = 768 + 256 / 768 *256 ,得到的结果向下取整为整数。这样在一个数据发送又接受到到对应ACK的一个周期(RTT),cwnd最多增加一个seg.size(原文:We want to increase cwnd by at most one segment each round-trip time, regardless how many ACKs are received in that RTT, whereas slow start will increment cwnd by the number of ACKs received in a round-trip time)。
4.3结束条件
没看到书上有写结束条件,cwnd一直增加直到大于win就会被忽略。
5 .fast retransmit & fast recovery
当发生第二种congetion就会执行 fast 算法,这两种算法是一起执行的。
5.1 fast retransmit
一般的retransmit需要等到超时。但采用fast retransmit后,连续收到大于等于三个重复的ACK(不包括第一个正常的确认ACK),就会retransmit。
当连续收到重复1或2个重复ACK时,可能是因为segment到达顺序错位导致的,不一定会有segment lost,但是收到2个以上的重复ACk就说明segment lost,因为segment在网络传输的时间不会那么久。
5.2 fast recovery
一般超时重发后会执行slow start,但这样会导致cwnd大降至seg.size。而发生第二种congetion说明TCP的数据流仍然正常,只不过是有一个segment 丢失。所以不需要将cwnd减少太多,而是设成MIN(原cwnd, win)/ 2 + 3 * seg.size,接着每收到一个重复ACK,cwnd就加上seg.size,如果总的数据发送量没超过cwnd,那就再发送一个segment。