TCP 解决流水线的差错恢复 SR协议

选择重传(SR)协议通过让发送方重传那些它怀疑在接收方出错的分组而避免了不必要的重传。
这种个别的、按需的重传需要接收方逐个地确认正确接受的分组。

还是用窗口长度N来限制流水线中未完成、未被确认的分组数。
与GBN不同的事,发送方已经收到了窗口中某些分组的ACK。

与GBN不同的是,发送方已经收到了对窗口中某些分组的ACK。
发送方看到的窗口:
image

接收方将确认一个正确接收的分组(在窗口内),而不管其是否按序到达。 失序的分组将被缓存直到所有丢失分组都被收到。
接收方看到的窗口:
image

SR 发送方的系统调用与对应的操作

  1. send

    if 序号可用:
    	将数据打包并发送
    else:
    	缓存/返回上层以便之后传输
    
  2. timeout: 被用于防治丢失分组
    和GBN不同的是,每个分组都必须拥有自己的 逻辑定时器,因为超时发送后只能发送一个分组。
    可以使用单个硬件定时器模拟多个逻辑定时器的操作。

  3. 收到ack

if ack序号在窗口内:
	SR发送方将那个被确认的分组标记为已确认。
	while (send_base 已确认) send_base++
	1.中缓存的一些分组如果落在了窗口内,那么发送这些分组
else:

SR 接收方的系统调用与对应的操作

seq = n
if seq >= rcv_base && seq <= rcv_base + n - 1: 
	产生一个ack被回送给发送方
	while (rcv_base 已确认) rcv_base++
		并且交付给上层
else if seq <= rcv_base && seq <= rcv_base - 1:
	产生一个ack,即使该分组是接收方以前已经确认的分组
else:

else if seq <= rcv_base && seq <= rcv_base - 1:
产生一个ack,即使该分组是接收方以前已经确认的分组
这一步是非常关键的,假设之前收到的一个分组,然后返回其ack,且这个ack的序号=send_base,但是这个ack丢失了,那么发送方会重新发送这个分组,那么这个时候接收方虽然已经确认了这个分组,但是还是要去发送一个ack,以确保发送端的滑动窗口的send_base能够向右滑动。
这也表明发送方和接收方对于哪些分组已经正确被接收看到的并不总是一样的,这也意味着发送方和接收方的窗口并不是总是一致的。

窗口如果太小了话,发送方和接收方窗口间缺乏同步会产生严重的后果。
假设发送方发送0, 1,2,3。4个分组。窗口大小为3。
0,1,2都被接收方接收。 此时接收方的窗口元素为3 0 1
接下来考虑两种情况:

  • 0, 1, 2的ACK 都丢失了,然后发送方重新发送0,接收方对于这个0是接收还是不接收。
  • 前3个ACK都被正确交付,此时,发送方端口也为3 0 1, 然后后续 3的ACK丢失了,0的ACK到达了,这个时候不能确定这个0是第一个分组的重传还是第5个分组的发送。

因此,窗口的长度比序号空间小1时,协议是无法工作的, 规定: 窗口的长度必须小于等于序号空间大小的一般。

image

posted @   CrazyShanShan  阅读(229)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示