由于TCP序列号采用的是累计确认的方式,接收方没有收到报文5,但是收到了报文6 7 8,它只能反复的给发送方说我还需要报文5,这样发送方其实是不知道报文5没有发过去,到底6 7 8有没有发过去呢?
所以发送方要么采用积极的方法,重传5 6 7 8,要么采用乐观的方法,只重传5,下面将介绍选择性确认协议将更加有效的仅仅重传丢失的报文段。
仅重传丢失段
保守乐观
当server连续发送4个报文给client,而第三个报文丢失的时候,而我们的server是在第七步收到ACK,这个ACK是说第三个报文没有收到,接下来server怎么处理,这就有两种方式,第一种采用保守和乐观的方式,所谓乐观就是认为第四个帧应该是被对方收到了,seq序号是用累计确认的方式的,所以client没有办法去告诉server其实第四个帧我是收到了,server尽量乐观,所以仅仅发送第三个部分。
如果第四个报文也丢失的情况下,这里的效率就出现了问题。
重传所有段 --积极悲观
重传所有段:积极悲观 可能浪费带宽
第二种方式就是积极悲观的态度,比如第三个报文没有发送过去,那么就将第三个和第四个报文都重发一次,这样我们认为整个网络丢包比较严重,所以我们的态度是比较悲观的。所以积极的将所有的段都发出去,带来的问题是可能浪费带宽,因为其实第4个报文是发送给client的。
如果整个网络当中真的在大量丢包的时候我们现在重发所有的段,那么会导致效率更加的低下。
怎么解决保守乐观和积极悲观各自的问题呢?TCP引入了选择性确认。
SACK:TCP Selective Acknowledgment
option部分演示过,如果type选为4,那么表示我们将支持SACK这个功能,如果类型是5,我们后面总长度字节数就可以去携带以及收到哪些失序的报文段。
引入SACK
有了sack选择性确认技术之后,当我们server连续发送4个报文,而client先收到第四个部分,没有收到第三个报文时候,他就可以在ACK确认帧中,对于ack的number仍然说的是第三个报文我没有收到,但是加了sack说361-500,也就是第四个报文的序列号我收到了,这个时候server就可以针对性的知道第四个报文已经收到了,我们只需要发第三个报文。
所以server不用陷入选择悲观和乐观的方式。
• 选择性确认
SACK
- Left Edge of Block
- Right Edge of Block
在实际的抓包报文当中可以看到SACK,在option当中有left和right。