TCP通信时,如果发送序列中间某个数据包丢失,TCP会通过重传最后确认的包开始的后续包,
这样原先已经正确传输的包也可能重复发送,急剧降低了TCP性能。为改善这种情况,发展出
SACK(Selective Acknowledgment, 选择性确认)技术,使TCP只重新发送丢失的包,不用
发送后续所有的包,而且提供相应机制使接收方能告诉发送方哪些数据丢失,哪些数据重发了,
哪些数据已经提前收到等
SACK选项
SACK信息是通 过TCP头的选项部分提供的,信息分两种,一种标识是否支持SACK, 在TCP
握手时发送;另一种是具体的 SACK 信息。
SACK 允许选项
类型值为4
+---------+---------+
| Kind=4 | Length=2|
+---------+---------+
该选项只允许在有SYN标志的TCP包中,也即TCP握手的前两个包中,分别表示各自是否支
持 SACK
SACK 选项
类型值为5
+--------+--------+
| Kind=5 | Length |
+--------+--------+--------+--------+
| Left Edge of 1st Block |
+--------+--------+--------+--------+
| Right Edge of 1st Block |
+--------+--------+--------+--------+
| |
/ . . . /
| |
+--------+--------+--------+--------+
| Left Edge of nth Block |
+--------+--------+--------+--------+
| Right Edge of nth Block |
+--------+--------+--------+--------+
选项长度可变,但由于整个TCP选项长度不超过40字节,实际最多不超过4组边界值
该选项参数告诉对方已经接收到并缓存的不连续的数据块,注意都是已经接收的,发送方可
根据此信息检查究竟是哪个块丢失,从而发送相应的数据块。
* Left Edge of Block
不连续块的第一个数据的序列号
* Right Edge of Block
不连续块的最后一个数据的序列号之后的序列号
表示(Left Edge - 1)和(Right Edge)处序列号的数据没能接收到
SACK的产生
SACK 通常都是由TCP接收方产生的,在TCP握手时如果接收到对方的 SACK 允许选项同时
自己也支持 SACK 的话,在接收异常时就可以发送 SACK 包通知发送方
对中间有丢包或延迟时的 SACK
如果TCP接收方接收到非期待序列号的数据块时,如果该块的序列号小于期待的序列号,说明
是网络复制或重发的包, 可以丢弃 ;如果收到的数据块序列号大于期待的序列号,说明中间包
被丢弃或延迟,此时可以发送 SACK 通知发送方出现了网络丢包。
为反映接收方的接收缓存和网络传输情况, SACK 中的第一个块必须描述是那个数据块激发此
SACK 选项的,接收方应该尽可能地在 SACK 选项部分中填写尽可能多的块信息,即使空间有限
不能全部写完,SACK选项中要报告最近接收的不连续数据块,让发送方能了解当前网络传输情
况的最新信息。
对重发包的SACK(D-SACK)
RFC2883中对 SACK 进行了扩展,在 SACK 中描述的是收到的数据段,这些数据段可以是正常的,
也可能是重复发送的, SACK 字段具有描述重复发送的数据段的能力,在第一块 SACK 数据中描述
重复接收的不连续数据块的序列号参数,其他 SACK 数据则描述其他正常接收到的不连续数据,因
此第一块 SACK 描述的序列号会比后面的 SACK 描述的序列号大;而在接收到不完整的数据段的情
况下, SACK 范围甚至可能小于当前的ACK值。通过这种方法,发送方可以更仔细判断出当前网络
的传输情况,可以发现数据段被网络复制、错误重传、ACK丢失引起的重传、重传超时等异常的网
络状况
发送方对SACK的响应
TCP发送方都应该维护一个未确认的重发送数据队列,数据未被确认前是不能释放的,这个从重发
送队列中的每个数据块都有一个标志位“SACKed”标识是否该块被 SACK 过,对于已经被 SACK 过
的块,在重新发送数据时将被跳过。发送方接收到接收方 SACK 信息后,根据 SACK 中数据标志重
发送队列中相应的数据块的“SACKed”标志,但如果接收不到接收方数据,超时后,所有重发送队
列中数据块的SACKed位都要清除,因为可能接收方已经出现了异常。
SACK应用举例
发送方发送的数据 接收方接收的数据 接收方发送的ACK(包括 SACK )
SACK 累加接收的数据
5000-5499 (该包丢失)
5500-5999 5500-5999 5000, SACK =5500-6000
6000-6499 6000-6499 5000, SACK =5500-6500
6500-6999 6500-6999 5000, SACK =5500-7000
7000-7499 7000-7499 5000, SACK =5500-7500
数据包丢失,ACK丢失
3000-3499 3000-3499 3500 (ACK包丢失)
3500-3999 3500-3999 4000 (ACK包丢失)
4000-4499 (该包丢失)
4500-4999 4500-4999 4000, SACK =4500-5000 (ACK包丢失)
3000-3499 3000-3499 4000, SACK =3000-3500, 4500-5000
---------此为D- SACK
数据段丢失和延迟
500-999 500-999 1000
1000-1499 (延迟)
1500-1999 (该包丢失)
2000-2499 2000-2499 1000, SACK =2000-2500
1000-2000 1000-1499 1500, SACK =2000-2500
1000-2000 2500, SACK=1000-1500
---------此为D-SACK
数据段丢失且延迟
500-999 500-999 1000
1000-1499 (延迟)
1500-1999 (该包丢失)
2000-2499 (延迟)
2500-2999 (该包丢失)
3000-3499 3000-3499 1000, SACK =3000-3500
1000-2499 1000-1499 1500, SACK =3000-3500
2000-2499 1500, SACK =2000-2500, 3000-3500
1000-2499 2500, SACK =1000-1500, 3000-3500
---------此为部分D- SACK
结论
通过 SACK 选项可以使TCP发送方只发送丢失的数据而不用发送后续全部数据,提高了数据的传输效率
这样原先已经正确传输的包也可能重复发送,急剧降低了TCP性能。为改善这种情况,发展出
SACK(Selective Acknowledgment, 选择性确认)技术,使TCP只重新发送丢失的包,不用
发送后续所有的包,而且提供相应机制使接收方能告诉发送方哪些数据丢失,哪些数据重发了,
哪些数据已经提前收到等
SACK选项
SACK信息是通 过TCP头的选项部分提供的,信息分两种,一种标识是否支持SACK, 在TCP
握手时发送;另一种是具体的 SACK 信息。
SACK 允许选项
类型值为4
+---------+---------+
| Kind=4 | Length=2|
+---------+---------+
该选项只允许在有SYN标志的TCP包中,也即TCP握手的前两个包中,分别表示各自是否支
持 SACK
SACK 选项
类型值为5
+--------+--------+
| Kind=5 | Length |
+--------+--------+--------+--------+
| Left Edge of 1st Block |
+--------+--------+--------+--------+
| Right Edge of 1st Block |
+--------+--------+--------+--------+
| |
/ . . . /
| |
+--------+--------+--------+--------+
| Left Edge of nth Block |
+--------+--------+--------+--------+
| Right Edge of nth Block |
+--------+--------+--------+--------+
选项长度可变,但由于整个TCP选项长度不超过40字节,实际最多不超过4组边界值
该选项参数告诉对方已经接收到并缓存的不连续的数据块,注意都是已经接收的,发送方可
根据此信息检查究竟是哪个块丢失,从而发送相应的数据块。
* Left Edge of Block
不连续块的第一个数据的序列号
* Right Edge of Block
不连续块的最后一个数据的序列号之后的序列号
表示(Left Edge - 1)和(Right Edge)处序列号的数据没能接收到
SACK的产生
SACK 通常都是由TCP接收方产生的,在TCP握手时如果接收到对方的 SACK 允许选项同时
自己也支持 SACK 的话,在接收异常时就可以发送 SACK 包通知发送方
对中间有丢包或延迟时的 SACK
如果TCP接收方接收到非期待序列号的数据块时,如果该块的序列号小于期待的序列号,说明
是网络复制或重发的包, 可以丢弃 ;如果收到的数据块序列号大于期待的序列号,说明中间包
被丢弃或延迟,此时可以发送 SACK 通知发送方出现了网络丢包。
为反映接收方的接收缓存和网络传输情况, SACK 中的第一个块必须描述是那个数据块激发此
SACK 选项的,接收方应该尽可能地在 SACK 选项部分中填写尽可能多的块信息,即使空间有限
不能全部写完,SACK选项中要报告最近接收的不连续数据块,让发送方能了解当前网络传输情
况的最新信息。
对重发包的SACK(D-SACK)
RFC2883中对 SACK 进行了扩展,在 SACK 中描述的是收到的数据段,这些数据段可以是正常的,
也可能是重复发送的, SACK 字段具有描述重复发送的数据段的能力,在第一块 SACK 数据中描述
重复接收的不连续数据块的序列号参数,其他 SACK 数据则描述其他正常接收到的不连续数据,因
此第一块 SACK 描述的序列号会比后面的 SACK 描述的序列号大;而在接收到不完整的数据段的情
况下, SACK 范围甚至可能小于当前的ACK值。通过这种方法,发送方可以更仔细判断出当前网络
的传输情况,可以发现数据段被网络复制、错误重传、ACK丢失引起的重传、重传超时等异常的网
络状况
发送方对SACK的响应
TCP发送方都应该维护一个未确认的重发送数据队列,数据未被确认前是不能释放的,这个从重发
送队列中的每个数据块都有一个标志位“SACKed”标识是否该块被 SACK 过,对于已经被 SACK 过
的块,在重新发送数据时将被跳过。发送方接收到接收方 SACK 信息后,根据 SACK 中数据标志重
发送队列中相应的数据块的“SACKed”标志,但如果接收不到接收方数据,超时后,所有重发送队
列中数据块的SACKed位都要清除,因为可能接收方已经出现了异常。
SACK应用举例
发送方发送的数据 接收方接收的数据 接收方发送的ACK(包括 SACK )
SACK 累加接收的数据
5000-5499 (该包丢失)
5500-5999 5500-5999 5000, SACK =5500-6000
6000-6499 6000-6499 5000, SACK =5500-6500
6500-6999 6500-6999 5000, SACK =5500-7000
7000-7499 7000-7499 5000, SACK =5500-7500
数据包丢失,ACK丢失
3000-3499 3000-3499 3500 (ACK包丢失)
3500-3999 3500-3999 4000 (ACK包丢失)
4000-4499 (该包丢失)
4500-4999 4500-4999 4000, SACK =4500-5000 (ACK包丢失)
3000-3499 3000-3499 4000, SACK =3000-3500, 4500-5000
---------此为D- SACK
数据段丢失和延迟
500-999 500-999 1000
1000-1499 (延迟)
1500-1999 (该包丢失)
2000-2499 2000-2499 1000, SACK =2000-2500
1000-2000 1000-1499 1500, SACK =2000-2500
1000-2000 2500, SACK=1000-1500
---------此为D-SACK
数据段丢失且延迟
500-999 500-999 1000
1000-1499 (延迟)
1500-1999 (该包丢失)
2000-2499 (延迟)
2500-2999 (该包丢失)
3000-3499 3000-3499 1000, SACK =3000-3500
1000-2499 1000-1499 1500, SACK =3000-3500
2000-2499 1500, SACK =2000-2500, 3000-3500
1000-2499 2500, SACK =1000-1500, 3000-3500
---------此为部分D- SACK
结论
通过 SACK 选项可以使TCP发送方只发送丢失的数据而不用发送后续全部数据,提高了数据的传输效率