【CS144】Lab4总结

Lab汇总

概述

lab4要求实现一个将 T C P R e c e i v e r TCPReceiver TCPReceiver T C P S e n d e r TCPSender TCPSender结合起来的 T C P C o n n e c t i o n TCPConnection TCPConnection,实现真正意义上的 T C P TCP TCP实体。当收到一个 T C P S e g m e n t TCPSegment TCPSegment时, T C P C o n n e c t i o n TCPConnection TCPConnection需要将该报文分别交付给 T C P R e c e i v e r TCPReceiver TCPReceiver T C P S e n d e r TCPSender TCPSender进行解析(调用 R e c e i v e r Receiver Receiver S e n d e r Sender Sender中相应的接口),进行全局的统筹协调。当经过一定的时间段,操作系统会调用 C o n n e c t i o n Connection Connection中的 t i c k tick tick函数进行时间记录(方便测试), C o n n e c t i o n Connection Connection将通知 S e n d e r Sender Sender此时经过的时间,方便 S e n d e r Sender Sender进行超时重传。

实现细节

TCP实体

T C P TCP TCP实体由三部分组成:

  • 接收方:当从网络中接收到一个 T C P TCP TCP报文段时,会调用 T C P C o n n e c t i o n TCPConnection TCPConnectionsegment_received接口进行处理

    • 如果报文段头部中的RST标记被设置为1,则对该 T C P TCP TCP实体执行非洁净关闭( u n c l e a n   s h u t d o w n unclean\ shutdown unclean shutdown)操作。

    • 否则

      • 将该TCP报文段交给 R e c e i v e r Receiver Receiver处理(通过 R e c e i v e r Receiver Receiversegment_received接口)
      • 且如果该 T C P TCP TCP报文段设置了ACK标志,则将其中的ackno字段与window_size字段交给 S e n d e r Sender Sender进行更新(通过ack_received接口)。
      • 当收到的报文段占有字节序号时(length_in_sequence_space返回值不为零), C o n n e c t i o n Connection Connection需要确保其至少回应一个报文段,以更新此时 R e c e i v e r Receiver Receiver中维护的acknowindow_size
      • 最后有一个特殊情况需要处理,对方终端可能会发送一个拥有不合法字节序号的报文用来检测你的 T C P TCP TCP实体是否仍然存活,此时需要发送一个空报文进行回复(会携带acknowindow_size)。这种情况下的处理代码如下:(从给定的代码中可以看出,这种情况应该是规定好的,跟着写就是了)
      if (_receiver.ackno().has_value() && (seg.length_in_sequence_space() == 0)
          && seg.header().seqno == _receiver.ackno().value() - 1) {
          _sender.send_empty_segment();
      }
      
  • 发送方:每隔一段时间将调用发送方的接口对输入缓冲区中的字节流进行打包并发送

    • 每隔一段时间(当 C o n n e c t i o n Connection Connection中的 t i c k tick tick函数被调用的时候),如果 S e n d e r Sender Sender中的输入缓冲区stream_in已经被写入字节,那么需要调用 S e n d e r Sender Sender中的fill_window接口进行字节流的打包和发送
    • 在发送 T C P TCP TCP报文段之前, C o n n e c t i o n Connection Connection需要询问 R e c e i v e r Receiver Receiver当前的acknowindow_size,并添加到每一个报文段的相关字段中(如果ackno存在,则设置ACK标记为1)
  • 时间流逝:当 C o n n e c t i o n Connection Connection中的 t i c k tick tick接口被调用时

    • 调用 S e n d e r Sender Sender中的tick接口告知时间流逝
    • 如果此时超时重传次数超出上限,则进行非洁净关闭
    • 如果此时满足洁净关闭的要求(见下一节),则执行洁净关闭

关闭TCP连接

  • 不洁净关闭
    当接收或发送一个带RST标记的 T C P TCP TCP报文段时,将会启动不洁净关闭,即将当前 T C P TCP TCP实体的输入输出字节流都设置为出错状态,并将此实体设置为未激活状态(active()接口返回false)。
  • 洁净关闭
    如果本地 T C P TCP TCP想要进行洁净关闭,首先要满足三个条件:
    1、接收方的inbound stream已经拼接完全且输入停止(input ended)
    2、发送方的outbound stream已经停止输入且被完全发出(即已经eof)
    3、发送方发出的所有报文段均被确认
    当本地 T C P TCP TCP满足以上三个条件,并确认对方 T C P TCP TCP已经满足上述三个条件时,可以进行洁净关闭,又分为以下两种情况:
    • 本地 T C P TCP TCPinbound stream停止输入(input ended)但outbound stream还未到达eof(即还未发送完,但是已经接受完了),那么此时对方 T C P TCP TCP已经满足上述的条件2;当本地 T C P TCP TCP满足上述三个条件时,它能够百分百确定对方 T C P TCP TCP已经满足三个条件。因为此时,对方 T C P TCP TCP必然满足条件1和2,且由于对方 T C P TCP TCP的数据比本地 T C P TCP TCP的数据早发完,则本地 T C P TCP TCP在发送剩余数据时,必然会携带对远程 T C P TCP TCP所有 T C P TCP TCP报文段的确认号,又因为本地 T C P TCP TCP发送方的所有报文均被确认,故能够确认对方 T C P TCP TCP肯定收到过自己的确认号,即已经满足条件3.
    • 本地 T C P TCP TCP不能够百分百的确认对方已经收到所有的确认号,故需要等待一段时间(10*_cfg.rt_timeout),如果在时间内未收到对方 T C P TCP TCP的报文,则说明对方大概率已经收到所有的确认,因为没有产生超时重传。

坑点

  • 一开始不太清楚time_since_last_segment_received这个字段怎么维护,查阅了相关博客得知,由于系统是通过调用 t i c k tick tick函数来跟踪时间的,于是只需要在 t i c k tick tick函数被调用时累加即可,在接收到 T C P TCP TCP报文时将累计的时间情况即可。
  • C o n n e c t i o n Connection Connection t i c k tick tick函数被调用时,需要进行报文段的发送(即调用 S e n d e r Sender Senderfill_window接口)。注意如果 S e n d e r Sender Sender的输入缓存区如果还未写入字节的话,则不需要调用fill_window进行报文段的发送,否则会进入到SYN_SENT状态从而出错。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值