1.累计ACK
我们之前说TCP数据是分段(segment)发送的,发送端发送一段,接收端回复一个ACK。而且ACK可以依附在数据上进行回复。但是每段回复一个小小的ACK貌似有点占用流量。累计ACK的意思是,7,8,9段在滑窗内,8和9段已经收到了,这时如果7段接收到了,那么7,8段的ACK就不必发了。因为ACK是告诉发送端发送下一个段,而9段之前完全都接收到了,那么直接发送9段的ACK即可。
接收端在回复ACK时都会有一些延迟,这时如果有后续产生的ACK数据段,那么ACK就采用累计发送的方式。这样可以节省一些流量。
2.滑窗结构
滑窗是以byte表示大小的。
发送端:(offered window)分为两部分。Not Received ACK和Being send。第一块意思是还没收到ACK回复,第二块意思是待发送。
接收端:(received window)分为两部分。Received ACK && Not send to proc和Advertise Window。第一块代表着ACK回复过了,端口缓冲区接到数据了,但是程序还没有处理。这样就会占用缓冲区的大小。Advertise Window 又可分为Received && not ACKed 和Not Received。Advertise Window的大小如果为0,则无法继续处理发送端传来的数据。又或者发送端速率大于接收端速率,也注定会有数据溢出。
3.流量控制
我们看到了Advertise window窗口的变化必须要让发送端知道。这样发送端得到Advertise window后,调整offered window的大小,窗口一变小发送速率就降下来了。
如果Advertise window的大小为0时,发送方知道后会停止发送,并隔一段时间进行窗口探测。也就是发送1byte大小的TCP段,如果探测回来仍然为0,那就延迟更长时间后再探测。
如果Advertise window大小不为0,但是很小。这时候TCP发送很小的数据,之后接收端处理又腾出来一段很小的空间,那么发送端傻乎乎地每次发一小段数据。而数据中TCP的头部占用极大的空间,数据很小。这样就造成一些流量的浪费。为避免这种情况,TCP规定:
接收端的敞口也要有一定的长度否则等待;发送端发送的数据要有一定的长度,否则等待。
4.超时重新发送
发送端发送出片段时,开始计时。如果超过RTO时间未收到ACK回复则会认为该段丢失,从而重新发送。但是超时时间怎么算呢?网络情况不同,设置的超时时间也应该不同。一般情况下,采样传输往返时间来决定。发送端通过采样获得传输的平均时间,通过平均时间加上误差即可设置超时时间。这种设置方法是以平均值为基本参照的,但是方差的大小同样也反应了网络的状况。方差越大,网络越不稳定,此时设置的超时时间也应越大。
5.快速重新发送
快速重新发送是优于超时重新发送的策略。应用的场景如7,8,9段先收到9段,但8段还没收到。这时会发送ACK8,向发送端寻求8段。这时如果继续收到后面的段,那么接收端会继续回复ACK8段。如果继续接收的是乱序,则接收端会继续要求ACK8。如果发送了3次ACK,那么发送端就会终止计时,立即发送8段。这就是所谓的快速重发。之所以叫快速重发,是相较于超时重发而言的。