CS144 Lab Checkpoint 2: the TCP receiver

Overview

TCPReceiver 从对等的sender接收消息,使用 receive() 方法,然后调用 Reassembler() 方法,后者写入 ByteStream 中 然后应用程序从 ByteSteam 中读取。
同时,TCPReceiver 还会通过 send() 方法给sender发送消息,告诉sender:

  1. 确认号ackno ,这是接收方需要从发送方接受的第一个字节;
  2. ByteStream的可用容量,也就是窗口大小 window size

本实验最难的部分在于如何思考 TCP 将如何表示每个字节在流中的位置,也称为“序列号”。

Translating between 64-bit indexes and 32-bit seqnos

TCP协议中包含三种序号分别是:seqnoabsolute seqnostream index,其转换关系如图所:示:
在这里插入图片描述
在这里插入图片描述
可以看到,absolute Seqno和stream index只是在开头和结尾的SYN和FIN有差异,且都是64位,所以第一个问题是如何实现seqno和absolute seqno之间的转换。

absolute seqno 到 seqno

首先,seqno有一个随机数ISN,作为起始序列编码,而absolute seqno从0开始,可以得到两者之间的转换关系为:
s e q n o ≡ a b s o l u t e s e q n o + I S N ( m o d 2 32 ) seqno \equiv absolute \, seqno + ISN (mod \, 2^{32}) seqnoabsoluteseqno+ISN(mod232)
所以wrap函数实现如下:

Wrap32 Wrap32::wrap( uint64_t n, Wrap32 zero_point )
{// Your code here.return Wrap32 { zero_point.raw_value_ + static_cast<uint32_t>(n)};
}

seqno 到 absolute seqno

和上面的类似,现在反向推倒absolute seqno
a b s o l u t e s e q n o ≡ s e q n o − I S N ( m o d 2 32 ) absolute \, seqno \equiv seqno - ISN (mod \, 2^{32}) absoluteseqnoseqnoISN(mod232)

这样就可以得到absolute seqno的低32位,然后在函数中给出了checkpoint,现在的目标是找出离checkpoint最近的absolute seqno的高32位,这个值一定满足:

c h e c k p o i n t − 2 31 ≤ a b s o l u t e s e q n o ≤ c h e c k p o i n t + 2 31 checkpoint - 2^{31}\leq absolute \, seqno \leq checkpoint + 2^{31} checkpoint231absoluteseqnocheckpoint+231
之所以满足这个条件,是因为如果不在这个范围内,则可以通过+或者- 2 32 2^{32} 232来更接近checkpoint。

所以高32位的计算方法是通过给checkpoint + 或者 - 2 31 2^{31} 231再取出其中的高32位,然后找出两个中接近checkpoint的值,即为所求。

uint64_t Wrap32::unwrap( Wrap32 zero_point, uint64_t checkpoint ) const
{// Your code here.uint32_t low32_bits = this->raw_value_ - zero_point.raw_value_; uint64_t high32_bits1 = (checkpoint + (1 << 31)) & 0xFFFFFFFF00000000;uint64_t high32_bits2 = (checkpoint - (1 << 31)) & 0xFFFFFFFF00000000;uint64_t aseqno1 = low32_bits | high32_bits1;uint64_t aseqno2 = low32_bits | high32_bits2;if(max(aseqno1,checkpoint) - min(aseqno1,checkpoint) < max(aseqno2,checkpoint) - min(aseqno2,checkpoint))return aseqno1;return aseqno2;
}

Implementing the TCP receiver

实验的剩余部分,要求我们实现TCPReceiver,实现:

  1. 从sender接收消息,并调用Reassembler对ByteStream重组;
  2. 将包含确认号ackno和窗口大小发送给sender.

首先添加几个成员变量和修改构造函数

class TCPReceiver
{
public:// Construct with given Reassemblerexplicit TCPReceiver( Reassembler&& reassembler ) : reassembler_( std::move( reassembler ) ) ,isn(-1), open(false),_capacity (std::min((size_t)reassembler_.writer().available_capacity(),(size_t)UINT16_MAX)){}/** The TCPReceiver receives TCPSenderMessages, inserting their payload into the Reassembler* at the correct stream index.*/void receive( TCPSenderMessage message );// The TCPReceiver sends TCPReceiverMessages to the peer's TCPSender.TCPReceiverMessage send() const;// Access the output (only Reader is accessible non-const)const Reassembler& reassembler() const { return reassembler_; }Reader& reader() { return reassembler_.reader(); }const Reader& reader() const { return reassembler_.reader(); }const Writer& writer() const { return reassembler_.writer(); }private:Reassembler reassembler_;Wrap32 isn;                   // zero_pointbool open;                    // ISNsize_t _capacity;             // 容量,最大为UINT16_MAX
};

然后修改成员函数,其中有三个特殊的标志位,分别是:
SYN:接收到SYN才开始传输报文,此前的全部丢弃
FIN:接收到FIN就结束传输报文
RST:接收到RST就将ByteSteam置错,并且停止传输。

所以在receive函数里:

  1. 先判断RST信号,如果出现RST,就给reader()置错;
  2. 判断是否有SYN,之前没有就丢弃,否则就记录ISN;
  3. 根据已经push进重组器的字节数为checkpoint,以ISN和checkpoint调用前面写的unwarp函数计算绝对序列号;
  4. 如上一问所述,在stream中索引并不是完全和64位的绝对索引相同的,stream中的索引不包括SYN和FIN,所以要判断一下。

值得注意的是,我第一次在实现这个转换的时候以为SYN始终都不会进入stream中,实际上不是这样的,第一个SYN的序列号作为ISN是会进入stream中,而其后的各报文的SYN端不会进入stream,FIN在后文也需要判断,所以我们需要根据报文的SYN标志对stream index和absolute seqno之间进行转换。

接下来在send函数,其中RST根据reader()是否出现error,而windows size则根据总大小减去重组器中已经存储的大小,接下来主要介绍ackno的计算:

  1. 如果还没有建立连接,即还没有SYN,就直接回复空(nullopt);
  2. 否则,就根据已经push进重组器的字节 + 1(确认号是下一个需要的序列号,所以加1),这里又需要判断是否是FIN,如果是,因为FIN也要占一个绝对序列号,所以还要再加1;
  3. 调用wrap转换成seqno,并返回message。
void TCPReceiver::receive( TCPSenderMessage message )
{// Your code here.if ( message.RST ) {reassembler_.reader().set_error();return;} if ( open == false ) {if ( !message.SYN )return;else {open = true;isn = message.seqno;}}Wrap32 seqno = message.seqno;uint64_t checkpoint = reassembler_.writer().bytes_pushed();uint64_t ab_seqno = seqno.unwrap( isn, checkpoint );uint64_t index = message.SYN ? ab_seqno : ab_seqno - 1;reassembler_.insert( index, message.payload, message.FIN );
}TCPReceiverMessage TCPReceiver::send() const
{// Your code here.TCPReceiverMessage message;if ( !open ) {message.ackno = nullopt;} else {uint64_t ab_seqno = reassembler_.writer().bytes_pushed() + 1 + ( reassembler_.writer().is_closed() ? 1 : 0 );message.ackno = Wrap32::wrap( ab_seqno, isn );}message.RST = reassembler_.reader().has_error();message.window_size = _capacity - reassembler_.reader().bytes_buffered();return message;
}

实验结果
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/71516.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring Boot 3.x 核心注解详解与最佳实践

Spring Boot 3.x 核心注解详解与最佳实践 前言 随着Spring Boot 3.x的正式发布&#xff0c;这个基于Spring Framework 6的里程碑版本带来了诸多新特性。本文将深入剖析Spring Boot 3.x的核心注解体系&#xff0c;结合代码示例讲解其作用及使用场景&#xff0c;助您快速掌握新…

PHP之常量

在你有别的编程语言的基础下&#xff0c;你想学习PHP&#xff0c;可能要了解的一些关于常量的信息。 PHP中的常量不用指定数据类型&#xff0c;可以使用两次方法定义。 使用const //定义常量 const B 2; echo B . PHP_EOL;使用define define("A", 1); echo A . P…

计算机网络——子网掩码

一、子网掩码是什么&#xff1f;它长什么样&#xff1f; 子网掩码的定义 子网掩码是一个32位的二进制数字&#xff0c;与IP地址“配对使用”&#xff0c;用于标识IP地址中哪部分属于网络地址&#xff0c;哪部分属于主机地址。 示例&#xff1a;IP地址 192.168.1.10&#xff0c;…

Tomcat-web服务器介绍以及安装部署

一、Tomcat简介 Tomcat是Apache软件基金会&#xff08;Apache Software Foundation&#xff09;的Jakarta 项目中的一个核心项目&#xff0c;由Apache、Sun和其他一些公司及个人共同开发而成。 Tomcat服务器是一个免费的开放源代码的Web应用服务器&#xff0c;属于轻量级应用…

分布式存储—— HBase数据模型 详解

目录 1.3 HBase数据模型 1.3.1 两类数据模型 1.3.2 数据模型的重要概念 1.3.3 数据模型的操作 1.3.4 数据模型的特殊属性 1.3.5 CAP原理与最终一致性 1.3.6 小结 本文章参考、总结于学校教材课本《HBase开发与应用》 1.3 HBase数据模型 在开始学习HBase之前非常…

android中activity1和activity2中接收定时消息

android中activity1和activity2中接收定时消息 业务类 import java.util.Timer; import java.util.TimerTask;public class MyAnager {private MyAnager() {}private static MyAnager instance;//回调接口onRecvTaskpublic interface OnMsgListener {void onRecvTask(String a…

BitMap实现用户签到、UV统计

1. Redis 的 BitMap 概述 在 Redis 中&#xff0c;BitMap 并非一种独立的数据结构&#xff0c;而是基于 String 类型数据结构实现的一种存储方式。由于 String 类型的最大上限是 512M&#xff0c;换算成 bit 位就是 2^32 个&#xff0c;这决定了 BitMap 可操作的最大范围。Bit…

共享模型之管程(悲观锁)

共享模型之管程&#xff08;悲观锁&#xff09; 文章目录 共享模型之管程&#xff08;悲观锁&#xff09;一、常见线程安全的类二、对象头三、Monitor&#xff08;监视器 / 管程&#xff09;四、偏向锁偏向锁的实现原理撤销偏向锁 五、轻量级锁轻量级锁的释放 六、重量级锁七、…

网络安全ctf试题 ctf网络安全大赛真题

MISC 1 签到 难度 签到 复制给出的flag输入即可 2 range_download 难度 中等 flag{6095B134-5437-4B21-BE52-EDC46A276297} 0x01 分析dns流量&#xff0c;发现dns && ip.addr1.1.1.1存在dns隧道数据&#xff0c;整理后得到base64: cGFzc3dvcmQ6IG5zc195eWRzIQ 解…

centos7操作系统下安装docker,及查看docker进程是否启动

centos7下安装docker&#xff0c;需要用到的yun命令 &#xff08;yum命令用于添加卸载程序&#xff09; 1.设置仓库&#xff1a; yum-config-manager \--add-repo \http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo 2.安装 Docker Engine-Community yum in…

私有云基础架构与运维(二)

二.私有云基础架构 【项目概述】 经过云计算基础知识及核心技术的学习后&#xff0c;希望进一步了解 IT 基础架构的演变过 程&#xff0c;通过学习传统架构、集群架构以及私有云基础架构的相关知识&#xff0c;认识企业从传统 IT 基 础架构到私有云基础架构转型的必要性。…

Linux 系统不同分类的操作命令区别

Linux 系统有多种发行版,每种发行版都有其独特的操作命令和工具。以下是一些常见的分类及其操作命令的区别: 1. 基于 Red Hat 的发行版 (RHEL, CentOS, Fedora) 1.1 包管理 安装软件包: bash复制 sudo yum install <package> 更新软件包: bash复制 sudo yum update…

‌PLC数据类型和‌C#数据类型的数据类型映射表

数据类型映射表 ‌PLC数据类型‌C#数据类型读取方式‌补充说明BitboolDBX布尔值BytebyteDBB单字节无符号整数WordushortDBW16位无符号整数DWorduintDBD32位无符号整数Intshort16位有符号整数DIntint32位有符号整数RealfloatDBR单精度浮点数LRealdoubleDBL双精度浮点数Stringstr…

windows部署spleeter 版本2.4.0:分离音频的人声和背景音乐

windows部署spleeter 版本2.4.0&#xff1a;分离音频的人声和背景音乐 一、Spleeter 是什么&#xff1f; Spleeter 是由法国音乐流媒体公司 Deezer 开发并开源的一款基于深度学习的音频分离工具。它能够将音乐中的不同音轨&#xff08;如人声、鼓、贝斯、钢琴等&#xff09;分…

QTS单元测试框架

1.QTS单元测试框架介绍 目前QTS项目采用C/C语言,而CppUnit就是xUnit家族中的一员,它是一个专门面向C的单元测试框架。因此,QTS采用CppUnit测试框架是比较理想的选择。 CppUnit按照层次来管理测试,最底层的就是TestCase,当有了几个TestCase以后&#xff0c;可以将它们组织成Te…

dify + ollama + deepseek-r1+ stable-diffusion 构建绘画智能体

故事背景 stable-diffusion 集成进 dify 后&#xff0c;我们搭建一个小智能体&#xff0c;验证下文生图功能 业务流程 #mermaid-svg-6nSwwp69eMizP6bt {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-6nSwwp69eMiz…

分享几个论文校对相关的deepseek提示词

论文校对 1.检查这段文字是否有语法或风格错误&#xff1a;[在此处粘贴您的文本]。 2.审查我的[文件类型&#xff0c;例如&#xff0c;“论文”]中的这一段落是否有语法或风格错误&#xff1a;[在此处粘贴您的文本]。 3.请审查我关于[具体主题&#xff0c;例如&#xff0c;…

【极光 Orbit•STC8A-8H】02. STC8 单片机工程模板创建

【极光 Orbit•STC8A-8H】02. STC8 单片机工程模板创建 七律 单片机 小小芯片大乾坤&#xff0c;集成世界在其中。 初学虽感千重难&#xff0c;实践方知奥妙通。 今天的讲法和过去不同&#xff0c;直接来一个多文件模块化的工程模板创建&#xff0c;万事开头难&#xff0c;…

mac安装nvm=>node=>nrm

下载并安装 NVM 运行以下命令下载并安装 NVM&#xff1a; curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.4/install.sh | bash 配置环境变量 vim ~/.zshrc 按 i 将如下代码复制进去&#xff0c;controlc &#xff0c;再按 :wq完成编辑 export NVM_DIR…

K8S学习之基础十一:k8s中容器钩子

容器钩子 容器钩子分为post-start和pre-stop post-start&#xff1a;容器启动后执行的命令 pre-stop&#xff1a;容器关闭前执行的命令&#xff0c;可用于优雅关闭 # 分别定义两个钩子&#xff0c;启动pod后更新index.html&#xff0c;关闭pod前正常关闭服务 vi post-pre.…