【CS144】Lab2总结

文章讲述了如何实现TCPReceiver,包括64位与32位序号的转换函数wrap和unwrap,以及TCP报文段的接收处理,如segment_received函数,关注SYN、FIN标志和Payload数据,使用StreamReassembler进行数据装配。
摘要由CSDN通过智能技术生成

Lab汇总

概述

利用lab0和lab1实现的ByteStream类和StreamReassembler类实现一个 T C P R e c e i v e r TCPReceiver TCPReceiver,即 T C P TCP TCP的接收功能。

Part1 真实序号与32位序号的相互转换

该部分主要实现StreamReassembler中64位的序号(从零开始)与 T C P TCP TCP头部中32位的序号(从某个随机初始序号开始)的相互转换。

将序号视为一个32位无符号整数(使用自然溢出方法对2的32次方取模)
一个字节流的初始序号对应着SYN标记,末尾序号对应着FIN标记,除去SYNFIN,中间是真正的字节内容(也就是说SYNFIN都占有着一个序号,即使报文中的数据部分没有数据)
比如文档中给出的例子(初始序号isn为2^32-2):
在这里插入图片描述

图片来源于lab文档

其中,

  • seqno就是TCP报文中的序号字段(32位无符号数)
  • absolute seqno是原字节流加上SYN与FIN之后的序号(从0开始递增)
  • stream index是原字节流的序号(不包括SYN和FIN,从0开始递增)

详细的字段描述如下图所示
在这里插入图片描述

图片来源于lab文档

具体实现

要求实现以下两个函数:

  • wrap函数
    该函数将absolute seqno转换为seqno,很简单,直接将64位无符号整数截取到32位无符号整数再加上初始序号(isn)即可

  • unwrap
    将给定的seqno转换为与某个给定值checkpoint(是一个absolute seqno)距离最近的一个absolute seqno,这个也不难(但是我很傻搞了一上午)
    我的思路如下(可能不太严谨)
    令给定的seqno的值为 n n ncheckpoint c k ck ck,则checkpoint转换为相应的seqno c k ′ = ( c k % 2 32 + i s n ) % 2 32 ck'=(ck \% 2^{32} + isn) \% 2^{32} ck=(ck%232+isn)%232
    假设 n n n转换成absolute seqno之后的值为 n ′ n' n,文档要求( n ′ n' n c k ck ck之间的间隔)与( n n n c k ′ ck' ck之间的间隔)一致。
    那么首先算出 n n n c k ′ ck' ck之间的间隔 d i f f = ( n − c k ′ + 2 32 ) % 2 32 diff=(n - ck' + 2^{32})\% 2^{32} diff=(nck+232)%232 d i f f diff diff也会等于 ( n ′ − c k + 2 32 ) % 2 32 (n' - ck + 2^{32}) \% 2^{32} (nck+232)%232
    d i f f + c k diff + ck diff+ck n ′ n' n 2 32 2^{32} 232下同余
    就是说 n’ = d i f f + c k + k ∗ 2 32 diff + ck + k * 2^{32} diff+ck+k232( k k k为任意整数)
    由于需要求出与 c k ck ck距离最近的一个 n ′ n' n,于是要么是 c k + d i f f ck + diff ck+diff要么是 c k + d i f f − 2 32 ck + diff - 2^{32} ck+diff232
    还有一个细节就是, c k + d i f f ck + diff ck+diff不用考虑溢出问题,但是 c k + d i f f − 2 32 ck + diff - 2^{32} ck+diff232 也就是 c k − ( 2 32 − d i f f ) ck - (2^{32} - diff) ck(232diff)可能会下溢出,此时就只能用 c k + d i f f ck + diff ck+diff
    参考代码如下:

uint64_t unwrap(WrappingInt32 n, WrappingInt32 isn, uint64_t checkpoint) {
    const uint32_t diff = static_cast<uint32_t>(n - wrap(checkpoint, isn));
    if (diff < (1U << 31)) return checkpoint + diff;
    else {
        uint64_t res = checkpoint - ((1UL << 32) - static_cast<uint64_t>(diff));
        if (res > checkpoint) res = checkpoint + diff;
        return res;
    }
}

Part2 实现 T C P R e c e i v e r TCPReceiver TCPReceiver

当收到一个 T C P TCP TCP的报文段时, R e c e i v e r Receiver Receiver只关注 T C P TCP TCP报文段头部的mermaid sequenceDiagram Numberseqno)、SYN标志位、FIN标志位和Payload数据部分
需要实现的函数有:

  • segment_received
    该函数为接收到一个 T C P TCP TCP报文段时, T C P R e c e i v e r TCPReceiver TCPReceiver的处理接口
    如果当前 T C P r e c e i v e r TCPreceiver TCPreceiver还未收到一个带有SYN标志的报文,且当前收到的报文中不带SYN标志,则丢弃该报文
    当收到的段中带有SYN标志时,需要保存一下initial sequence number
    只要已经收到带SYN标志的报文,则需要将数据部分调用 S t r e a m R e a s s e m b l e r StreamReassembler StreamReassemblerpush_substring方法将数据放入装配器中
    当报文带有FIN标志时,数据部分的最后一个字节即是该字节流的EOF
    调用push_substring方法时,需要将seqno转换为stream index(调用unwrap函数然后将结果减一即可);如果当前报文带有SYN标记,数据部分首字节的seqno需要加一;根据文档,unwrap函数的checkpoint选择最后一个reassembled的字节的absolute seqno

  • ackno
    该函数的功能为返回当前的acknowledge number
    注意加上SYNFIN占有的两个字节就可以啦

  • window_size
    返回当前缓存窗口(暂未放入接收窗口的比特范围)大小(容量减去当前接收窗口中的字节数)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值