Stanford CS144 lab3
- 总览
- lab3需要实现TCPSender ,TCPSender的作用是将发送字节流转化为TCPsegment
- 激动人心的是,在lab4中,将实现一个真实的TCPConnection,并通过它联通Internet世界
- TCP Sender
- TCPSender负责从一个ByteStream读取字节并将其转换成一序列外送TCP segments;另外,TCP revceiver可以是任何一个可靠的TCP receiver,建立一套Internet通信标准才是最重要的。
- TCPSender在TCPSegment中写入各个字段,比如序列号,SYN标志,有效载荷,FIN标志,TCPSender只能够读ackno和the window size这两个字段,标红的字段就是了
- TCPSender需要做的是
- 查看追踪接受者的window,也就是处理ackno与window size
- 尽可能填满窗口,也就是说及时的从ByteStream读数据,并创建与发送TCPsegments,直到the window满了或者ByteStream空了
- 跟踪查看哪个报文段流失了,我们将这种报文段称作
outstanding segments
,也就是未完成的报文段 - 对于
outstandin sgements
,需要做到超时重传,这里实现了ARQ,ARQ是OSI模型中数据链路层和传输层的错误纠正协议之一。它通过使用确认和超时这两个机制,在不可靠服务的基础上实现可靠的信息传输。如果发送方在发送后一段时间之内没有收到确认帧,它通常会重新发送。ARQ包括停止等待ARQ协议和连续ARQ协议,连续ARQ又分为回退N帧ARQ协议、选择性重传ARQ协议。ARQ协议是对滑动窗口的一个很好的实现
- TCPSender如何知道一个报文丢失了?
- TCPSender有一个计时器函数,也就是tick方法。TCP中超时的处理方式是:
每次超时重传最老的的报文段,并重新启动定时器;每次收到确认时,更新已被确认的报文段,重新启动计时器,如果还有未被确认大的报文段,重新启动定时器
- 每过几毫秒,TCPSender会调用
tick
函数,以此来及时,不要去调用其他⏲函数,比如time
或者clock
等 - 初始时,
RTO(retransmission timeout)
会被设置为initial value
,RTO
就是超时值,它变化,但是initial value
不会变化,变量initial_retransmission_timeout
保存了initial value
- 通过
RTO
实现重传计时器,这里的时间与真实时间并不一致 - 只要一个报文段发出了,不论是否是重传,计时器都会启动,并在
RTO
的时间之后,终止报警 - 所有的发出的报文段都收到了确认,停止计时器
- 计时器报警超时的话,需要重传最老的未收到确认的报文段,需要建立一些内部数据结构去记录
outstanding segment
, 这里的指数退避😵
,1.指数退避是重传的一种方法,并且这里是只重传最早的未被确认的报文,好处是使得网络拥塞减轻,但是慢,2.可以选择重传所有包,但是这样会加剧网络拥塞,3.还有其他策略,比如快重传,连续收到三个重复ACK(不包括第一个),便立刻重传,而这仍然存在是重传一个还是所有的问题。4.SACK可以解决这个问题,不过SACK存在接收方Reneging情况,所谓Reneging的意思就是接收方有权把已经报给发送端SACK里的数据给丢了。这样干是不被鼓励的,因为这个事会把问题复杂化了,但是,接收方这么做可能会有些极端情况,比如要把内存给别的更重要的东西。所以,发送方也不能完全依赖SACK,还是要依赖ACK,并维护Time-Out,如果后续的ACK没有增长,那么还是要把SACK的东西重传,另外,接收端这边永远不能把SACK的包标记为Ack
- TCPSender有一个计时器函数,也就是tick方法。TCP中超时的处理方式是:
- 实现TCP sender(看测试逐步实现是个不错的方式)
- 根据文档可以知道,我们不需要实现SR,只需要实现类似GBN,不过不同的是GBN要重传所有所有未确认分组
- 这个函数下一个lab要用
- 如果receiver的window为0,那么假设sender啥也不发,sender永远也没有机会接受到新的ack,即使receiver的window不再是0了
- 根据文档可以知道,我们不需要实现SR,只需要实现类似GBN,不过不同的是GBN要重传所有所有未确认分组
- 实现中的问题
- 这里需要特判TCPSegment中只有fin标志, 因为
Remember that the SYN and FIN flags also occupy a sequence number each, which means that they occupy space in the window.
- 初始的的
_receiver_window_size
需要设置为1,不然这个测试用例会出错,如果设置为0,会使的remain
溢出,也就是发完SYN
包之后,remain -= 1,会翻到最大值 - 这个测试用例需要特殊处理fin包的发送`
- window_size为零的时候需要特判,并且RTO不能指数退避,
- 需要特判重复的ack是无效的
不然会引发如下错误
- 在send_ack.cc中有个注释了的测试,它想要实现的效果是,如果传送的ackno过大,sender需要发送一个报文去告诉receiver
- 这里需要特判TCPSegment中只有fin标志, 因为
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端