小白:你这个想法其实也是挺不错的,不过如果分组n-1丢失了,那么按照GBN的重传规则,这时n-1和n都会被重传,这时之前缓存的n就没啥用了。而且,我们如果把n丢弃了,那么我们就不需要缓存任何失序的分组了,这样可以让我们的设计更加简单哦。
选择重传(SR)
回退N步协议的缺点也是很明显的,单个分组的差错能够引起GBN重传大量的分组,而且许多分组根本就没有必要重传。例如我们发送的序号为0-100,万一序号为1的分组出现了某些差错,这会导致1-100的分组会被重传,想想这是多么恐怖的事情啊。
因此,出现了选择重传这种协议。所谓“选择”,也就是有选择着去重传。
不过选择重传和回退N步是很相似的,只是在选择重传中,接收方收到失序的分组时,会把它缓存起来,直到拼凑到分组按序,才把分组传输给上一层。而发送方会为每个分组设置一个定时器,这样,只需要重传那些没有被接收方正确接收的分组就可以了。
我来个例子吧。
假设窗口长度N=6,这时A向B发送分组1-5。
当A收到序号为3的ACK,则状态如下:
注意,这个时候虽然序号3被确认接收了,但窗口并不能向右移动一格。
接下来受到序号为1的ACK,则:
这个时候窗口才可以向右移动一格。注意,黄色的那些序号是可以继续发送分组的,只是我没有继续填充发送而已。
接着收到序号为2的分组。
这个时候窗口向右移动了两个格。
接着继续这样接收下去,如果还有分组没发送的,就从nextseqnum开始填充发送...
如果某个分组超时了,就重新传输这个分组。
对于接收方B的窗口来说也差不多也一样,在此不展开。接收方对于失序的分组缓存起来,直到所有丢失的分组全部被收到为止,再把这批分组按序交付给上一层。
我在书上截了张完整的例子图: