【CS144】Lab3总结

概述

Lab3要求实现一个TCP sender(文档里真的谜语,也可能是我太菜了)

TCP Sender主要任务

  • 将输入字节流中的字节包装成一个一个的TCP报文段,主要关注报文段中的seqnoSYNFINPayload部分,并进行“发送”(塞入segment_out队列中即可)

  • 接收其他 T C P TCP TCP实体发送的报文,解析其中的Window Size字段和Ackno字段并将window size字段维护起来,获取接收窗口大小,根据接收窗口大小调整上述TCP报文段中的Payload大小;根据ackno确认某些缓存的请求,并将其弹出队列(某个报文能被确认当且仅当这个报文占有的所有序号在ackno以内)

  • 发送完一段报文之后,需要将给报文缓存下来(个人实现是放入一个队列中,segment_outstanding),方便之后超时重传

  • 维护一个超时计时器,在超时计时器超时重传seqno最小的一个缓存报文,即队头报文

超时计时器的实现

包含三个成员变量

  • _rto成员变量表示计时器启动至其超时的时候经过的毫秒数

  • _closed成员变量表示该超时计时器是否处于关闭状态

  • _time_left成员表示该超时计时器启动后剩余的时间

还有一系列成员函数,实现都比较简单:

//! \brief the TCP time keeper
class Timer {
  private:
    //! the retransmission timeout
    size_t _rto{0};
    //! the time left currently
    size_t _time_left{0};
    //! if the timer has been closed
    bool _closed{true};
  public:
    //! construtor
    Timer (const size_t& rto) : _rto(rto) {}
    //! \brief set the timer's RTO
    void set_rto(const size_t& rto) { _rto = rto; }
    //! \brief start the timer
    void start_timer() { _time_left = _rto; _closed = false; }
    //! \brief close the timer
    void close_timer() { _closed = true; }
    //! \brief double the retransmission timeout in the timer
    void double_rto() { _rto *= 2; }
    //! \brief if the time is closed
    bool is_closed() { return _closed; }
    //! \brief check if the timer is expired when call tick()
    bool is_expired(const size_t& ms_since_last_tick);
};

超时重传机制

对于超时重传机制,文档中是这样说的,跟着写就行了

  1. tick函数用于计时,该函数不需要你去调用它,只需要知道,在调用它的时候,据他上次被调用过去了多久(作为参数传进函数中),于是可以更新超时计时器的剩余时间。

  2. T C P S e n d e r TCPSender TCPSender在初始化的时候,会接受一个initial_retransmission_timeout的参数,这个参数作为计时器RTO的初始值

  3. 每当发送一个 T C P TCP TCP报文段时(非空),若超时计时器未启动,则将其启动

  4. 当所有的 o u t s t a n d i n g outstanding outstanding报文(也就是发送但未确认)都被确认时,将超时计时器关闭

  5. tick被调用且超时计时器超时的时候:

    • 重传最早发送的未被确认的 T C P TCP TCP报文(即队头)
    • 如果维护的window size字段不为0
      • 记录连续重传次数
      • 加倍超时计时器的RTO
    • 重新启动超时计时器(剩余时间设置为新的RTO
  6. T C P S e n d e r TCPSender TCPSender接收到一个有效的ackno时(确认了某些报文)

    • 设置超时计时器的RTO为初始值
    • 如果sender中仍存在outstanding的报文,则重启超时计时器
    • 重置连续重传次数为0

具体实现

为了实现以上所有功能, T C P S e n d e r TCPSender TCPSender中主要实现的函数有:
(这些函数实现就可以了,当且都不需要你调用,不要像我一样一开始傻里傻气的在ack_received里面调用fill_window函数)

fill_window函数

该函数的主要功能是,生成TCP报文段并将其发送,直至填满接收端的窗口或者发送方的字节流发送完毕,细节不多解释,主要讲一些坑点。

  • 首先就是需要严格按照文档中的状态图来实现这个函数(判断状态时可以使用状态图中的状态满足的条件)
    • 当前状态为CLOSED,则只能发SYN报文(只含SYN标记的报文,其实就是在第一次握手)
    • 当前状态为SYN_SENT,则不能发报文,等待接收到确认
    • 当前状态为SYN_ACKED,即收到了SYN报文的ACK确认,则可以根据维护的window_size进行报文发送
    • 当前状态为FIN_SENT,即已经发送完所有报文,停止发送,等待确认
    • 当前状态为FIN_ACKED,则收到所有确认(实际实现时不需要处理这个状态)
  • 然后就是发送报文的时候需要尽可能的去填满发送方的窗口,当报文大小比较大(超过MSS),则需要进行多次发送,说白了就是要循环发送,知道窗口被填满或者报文发完。

ack_received函数

这个函数主要用来处理接收方收到ackno之后的情况,按照文档来写就可以了,就是需要注意一个点,收到的ackno可能是不合法的(比当前发送出去的最大序列号还大),则需要抛弃掉。

tick函数

根据超时重传机制所讲的去实现就可以啦!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值