【CS144】Lab2总结
创始人
2024-05-29 20:22:41

Lab2

  • Lab汇总
  • 概述
  • Part1 真实序号与32位序号的相互转换
    • 具体实现
  • Part2 实现TCPReceiverTCPReceiverTCPReceiver

Lab汇总

概述

利用lab0和lab1实现的ByteStream类和StreamReassembler类实现一个TCPReceiverTCPReceiverTCPReceiver,即TCPTCPTCP的接收功能。

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

该部分主要实现StreamReassembler中64位的序号(从零开始)与TCPTCPTCP头部中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的值为nnn,checkpoint为ckckck,则checkpoint转换为相应的seqno为ck′=(ck%232+isn)%232ck'=(ck \% 2^{32} + isn) \% 2^{32}ck′=(ck%232+isn)%232
    假设nnn转换成absolute seqno之后的值为n′n'n′,文档要求(n′n'n′与ckckck之间的间隔)与(nnn与ck′ck'ck′之间的间隔)一致。
    那么首先算出nnn与ck′ck'ck′之间的间隔diff=(n−ck′+232)%232diff=(n - ck' + 2^{32})\% 2^{32}diff=(n−ck′+232)%232,diffdiffdiff也会等于(n′−ck+232)%232(n' - ck + 2^{32}) \% 2^{32}(n′−ck+232)%232
    即 diff+ckdiff + ckdiff+ck 与 n′n'n′ 在2322^{32}232下同余
    就是说 n’ = diff+ck+k∗232diff + ck + k * 2^{32}diff+ck+k∗232(kkk为任意整数)
    由于需要求出与ckckck距离最近的一个n′n'n′,于是要么是ck+diffck + diffck+diff要么是ck+diff−232ck + diff - 2^{32}ck+diff−232
    还有一个细节就是,ck+diffck + diffck+diff不用考虑溢出问题,但是ck+diff−232ck + diff - 2^{32}ck+diff−232 也就是 ck−(232−diff)ck - (2^{32} - diff)ck−(232−diff)可能会下溢出,此时就只能用ck+diffck + diffck+diff了
    参考代码如下:

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

Part2 实现TCPReceiverTCPReceiverTCPReceiver

当收到一个TCPTCPTCP的报文段时,ReceiverReceiverReceiver只关注TCPTCPTCP报文段头部的mermaid sequenceDiagram Numberseqno)、SYN标志位、FIN标志位和Payload数据部分
需要实现的函数有:

  • segment_received
    该函数为接收到一个TCPTCPTCP报文段时,TCPReceiverTCPReceiverTCPReceiver的处理接口
    如果当前TCPreceiverTCPreceiverTCPreceiver还未收到一个带有SYN标志的报文,且当前收到的报文中不带SYN标志,则丢弃该报文
    当收到的段中带有SYN标志时,需要保存一下initial sequence number
    只要已经收到带SYN标志的报文,则需要将数据部分调用StreamReassemblerStreamReassemblerStreamReassembler的push_substring方法将数据放入装配器中
    当报文带有FIN标志时,数据部分的最后一个字节即是该字节流的EOF
    调用push_substring方法时,需要将seqno转换为stream index(调用unwrap函数然后将结果减一即可);如果当前报文带有SYN标记,数据部分首字节的seqno需要加一;根据文档,unwrap函数的checkpoint选择最后一个reassembled的字节的absolute seqno

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

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

相关内容

热门资讯

苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...