CS144 lab2 tcp_receiver

1. 实验目的

lab2 的目的是实现tcp的接收端。

主要包括两方面

(1) 从发送端接收消息,使用Reassembler聚合字节流(Bytestream

(2)将确认号(ackno)和window size发回对端

确认号,也就是first_unassembler byte; 而Bytestream可写入的大小,

也就是window size!

acknowindow size两个共同描述了发送方能发送的数据范围。有时我们也叫

ackno⇔left edgeackno+window size⇔right edge ackno \Leftrightarrow left \ edge\\ ackno + window\ size \Leftrightarrow right\ edge acknoleft edgeackno+window sizeright edge

这个实验中最困难的部分在于TCP如何在流中表示每一个字节,也就是序列号(sequence number)。

2 实验内容

2.1 序列空间的转换

个人感觉是这个实验比较难的一部分。

我们在Reassebler中的索引是64位的,它足够大几乎不会重叠。

(假如传输速度为100Gbps, 几乎要花50年才能到达2642^{64}264, 而只需要1/3秒就能到达2322^{32}232)。

但在TCP中的序列空间是宝贵的,只有32位。这就带来了一些额外的问题:

  • wrap arround回滚,32位的序列空间只有4GB,0~232−12^{32}-12321, 超过了这个范围就又会从0开始
  • TCP seq numberTCP序列号为了安全,是从一个随机数开始的,它并不从0开始。开始的数我们叫它ISN(Initial Sequance Number, 初始随机数)。
  • SYN FIN各自占据一个序列号空间

我们这里就涉及到三种序列号索引空间了。

  • TCP 序列号索引
  • 绝对序列号
  • 流索引

文档中也给了差别比较的表格
在这里插入图片描述
在这里插入图片描述
序列号索引就是在TCP中的数字;而绝对序列号就是以0开始的,它不会发生回滚。面流索引就是收到的数据的标号了,就不包括SYN FIN

流索引和绝对序列索引就只差一个1

而序列号与绝对序列号的转换就需要我们实现了。

从绝对序列号转换为序列号,比较简单。

只需要zero_point + n就可以了。返回值就会自动回滚。

而让我感觉到最困难的就是323232位的序列号转换成646464位的绝对序列号了。

事实上文档中给出了解决的方法了,它的提示说不管如何转换。在32位的

序列号中的差值和64位绝对序列号中的差值肯定是一样的。

而它函数中的checkpoint则是离当前64位序列号最近的一个, 用first unassembler idx来充当。

为什么需要这个checkpoint呢?因为一个32位的seq number可以对应很多个64位的绝对序列号!!!

比如seqno=7 ,就可能对应7 7+2^{32} 7 + 2^{33} ... , 因此需要一个checkpoint来确定到底是哪一个,我们要的是离checkpoint最近的,比如说seqno = 7, checkpoint =6 + 2^{32},我们一下就能确定abs seqno=7 +2^{32}

这里还有个难点就是理解这个最近,由于32位置的空间它是回滚的,因此

距离也是有两个的!!!

在这里插入图片描述

还是看代码吧!

*wrapping_integers.cc

#include "wrapping_integers.hh"
#include "debug.hh"using namespace std;Wrap32 Wrap32::wrap( uint64_t n, Wrap32 zero_point )
{// Your code here.// debug( "unimplemented wrap( {}, {} ) called", n, zero_point.raw_value_ );return zero_point + static_cast<uint32_t>( n & 0xFFFFFFFF );
}uint64_t Wrap32::unwrap( Wrap32 zero_point, uint64_t checkpoint ) const
{// Your code here.// debug( "unimplemented unwrap( {}, {} ) called", zero_point.raw_value_, checkpoint );auto check_seq = wrap( checkpoint, zero_point).raw_value_;static constexpr uint64_t _2pow32 = static_cast<uint64_t> (1) << 32;uint64_t df1 = static_cast<uint64_t>( raw_value_ ) + _2pow32 - check_seq;if ( df1 >= _2pow32)df1 -= _2pow32;auto df2 = _2pow32 - df1;if ( df2 < df1 && checkpoint >= df2)return checkpoint - df2;elsereturn checkpoint + df1;}
2.2 实现tcp_receiver

实现这个tcp_receiver倒是没有实现序列号花的时间多。

状态管理也没有用状态机的那一套,用if-else过完样例。。。

主要遇到问题是,由于SYN它是需要占据一个序列号, 也就是ISN,而

之后数据中的zero_point应该是ISN + 1了。还有些小问题后面遇到测试

样例排查一下也能过。

最终还是看代码吧!

#include "tcp_receiver.hh"
#include "debug.hh"using namespace std;void TCPReceiver::receive( TCPSenderMessage message )
{// Your code here.// debug( "unimplemented receive() called" );// (void)message;if ( message.RST ) {this->reassembler_.reader().set_error();return ;}if ( message.SYN  && (not is_con)) {ISN = message.seqno ;is_con = true;}if ( is_con ) {Wrap32 cur{message.seqno};if (message.SYN)cur = cur + 1;uint64_t first_idx_ = cur.unwrap( ISN.value() + 1 , this->reassembler_.get_first_unassembler_idx());debug("payload: {}, size: {}, FIN: {}", message.payload, message.payload.size(), message.FIN ? "true": "false");this->reassembler_.insert( first_idx_, message.payload, message.FIN);}// first_idx
}TCPReceiverMessage TCPReceiver::send() const
{// Your code here.// debug( "unimplemented send() called" );// return {};TCPReceiverMessage msg{};if ( is_con ) {auto ackno = reassembler_.get_first_unassembler_idx();if (reassembler_.writer().is_closed())ackno++;msg.ackno = Wrap32::wrap(  ackno, ISN.value() + 1);}auto wnd_sz = reassembler_.writer().available_capacity() ;msg.window_size = wnd_sz > UINT16_MAX ? UINT16_MAX : wnd_sz ;msg.RST = reassembler_.writer().has_error();return msg;
}

3. 遇到的问题

  • 序列号转绝对序列号
  • FIN SYN需要占据一个序列号空间,这影响到了unwrap中的zero_point,同时在最后关闭时,ackno也需要多加1
  • bytestream中的available_capacityuint64_t, 而序列号空间最大UINT16_MAX,需要进行限制
  • RST标志位,需要根据RST来设置bytestream.set_error()

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

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

相关文章

【论文笔记】A Deep Reinforcement Learning Based Real-Time Solution Policy for the TSP

《基于 DRL 和 DCNN 的实时 TSP 求解策略》IEEE TRANSACTIONS ON INTELLIGENT TRANSPORTATION SYSTEMS, VOL. 24, NO. 6, JUNE 2023一段话总结本文提出了一种基于深度强化学习&#xff08;DRL&#xff09; 和深度卷积神经网络&#xff08;DCNN&#xff09; 的实时旅行商问题&am…

MMaDA:多模态大型扩散语言模型

集众家之所长&#xff0c;成大一统。普林斯顿大学、北京大学、清华大学、字节跳动的研究者将“文本推理、多模态分析、图像生成”三大方向融合在一个单一扩散模型里&#xff0c;并用恰当的优化策略来提升模型在各个方向的性能。 研究动机 研究人员致力于开发一个能够处理多种模…

容器技术入门与Docker环境部署

容器技术入门与Docker环境部署Docker概述什么是 DockerDocker 的优势Docker 的应用场景Docker 核心概念(1)镜像(2)容器(3)仓库Docker 安装1.关闭系统防火墙和内核2.下载Docker的repo文件3.替换仓库地址4.更新索引文件并安装Docker5.添加国内镜像站6.开启Docker服务7.优化内核参…

【01】MFC入门到精通—— MFC新建基于对话框的项目 介绍(工作界面、资源视图 、类视图)

文章目录1 创建工程2 运行3 工作界面介绍3. 1 类视图 Class View3.2 如何打开 类视图3.3 资源视图1 创建工程 选择菜单项 文件->新建->项目&#xff0c;弹出 “新项目” 对话框。 选择 MFC&#xff0c;点击下一步&#xff0c;然后键入工程名称&#xff0c;本例取名“Add…

2025!在Windows的Python中安装GDAL包(小白能成!)

最近更新 在2025.06.05日&#xff0c;GDAL发布预告&#xff1a;新版本将适配pipeline和向量读写功能。 直到2025.06.25日&#xff0c;最新的版本才算发行出来。 有朋友催我赶紧更新教程&#xff0c;我上次更新是3月份的时候了&#xff0c;恰好是GDAL上一个版本出来的时间。 前…

Python第一次作业

# 1.技术面试题**&#xff08;1&#xff09;TCP与UDP的区别是什么&#xff1f;****答&#xff1a;TCP 是 “可靠但较慢” 的协议&#xff0c;适合对数据完整性要求高的场景&#xff1b;UDP 是 “快速但不可靠” 的协议&#xff0c;适合对实时性要求高的场景。两者互补&#xff…

Linux【大数据运维】下制作Redis绿色免安装包(一)

linux下安装Redis比较繁琐&#xff0c;遇到内网部署环境更是麻烦。根据经验将Redis打包一个绿色版进行使用。 大体思路&#xff0c;在一台正常的机器上面制造好安装包&#xff0c;然后上传到内网服务器&#xff0c;解压使用。 下载&#xff1a; wget https://download.redis…

89104 PCIe Switch芯片国产替代 - PCIE5.0国产AI服务器高性能扩展,支持海光/龙芯/飞腾等

以下是针对89104 PCIe Switch芯片国产替代的高性能PCIe 5.0 AI服务器扩展方案的详细分析&#xff1a;一、核心国产替代芯片&#xff1a;TL63104控制器‌技术规格‌支持PCIe 5.0全速率&#xff08;32 GT/s&#xff09;&#xff0c;提供968 Lanes配置&#xff0c;聚合双向带宽达1…

Docker跨架构部署实操

需求场景 python项目&#xff0c;开发环境以及可供测试的环境为X86架构下的LINUX服务器&#xff0c;但正式环境需要部署在ARM架构下的麒麟服务器&#xff0c;且正式环境后续可能会长时间处于断网状态&#xff0c;需要一份跨架构的部署方案。 解决思路 在 X86 上打包、在 ARM&am…

JavaScript 树形菜单总结

树形菜单是前端开发中常见的交互组件,用于展示具有层级关系的数据(如文件目录、分类列表、组织架构等)。以下从核心概念、实现方式、常见功能及优化方向等方面进行总结。 一、核心概念 层级结构:数据以父子嵌套形式存在,如{ id: 1, children: [{ id: 2 }] }。节点:树形结…

【python实用小脚本-131】Python 实现 HTML 到 PDF 转换:解决文档处理痛点的高效工具

引言 在当今数字化办公环境中&#xff0c;文档格式的转换需求日益频繁。假设你是一位市场营销人员&#xff0c;需要将公司网站的产品介绍页面&#xff08;HTML 格式&#xff09;转换为 PDF 文档&#xff0c;以便用于线下宣传。然而&#xff0c;手动复制粘贴内容并调整格式不仅…

【Linux操作系统】简学深悟启示录:Linux基本指令

文章目录1.什么是操作系统&#xff1f;2.Xshell的使用3.常用指令3.1 ls指令3.2 pwd指令3.3 cd指令3.4 touch指令3.5 mkdir指令3.6 rmdir指令 && rm指令3.7 man指令3.8 cp指令3.9 mv指令3.10 cat指令3.11 echo指令&#xff08;重定向&#xff09;3.12 more指令3.13 less…

「py数据分析」04如何将 Python 爬取的数据保存为 CSV 文件

如何将 Python 爬取的数据保存为 CSV 文件 从原始网络数据到纯净 CSV - 搭建通往分析的桥梁 恭喜你&#xff01;经过前面的努力&#xff0c;你的 Python 脚本终于成功地从一个网站上爬取了数据&#xff0c;一个充满信息的宝库正静静地躺在你的变量中。但接下来呢&#xff1f;…

qemu vcpu的创建过程

在 QEMU 中&#xff0c;vCPU 线程的启动流程涉及多个阶段&#xff0c;包括初始化、线程创建和执行逻辑。以下是基于搜索结果的详细分析&#xff1a; QEMU vCPU 线程的启动流程 1. 初始化阶段 设备实例化&#xff1a;QEMU 使用 QOM&#xff08;QEMU Object Model&#xff09;系统…

Spring Security架构与实战全解析

Spring security1.安全架构1. 认证who are you登陆系统&#xff1a;用户系统2. 授权权限管理&#xff1a;用户授权3. 攻击防护xss (cross-site scripting)csrf (cross-site request forgery)cors (cross-origin resource sharing)sql注入4. 扩展&#xff1a;权限管理模型a. RBA…

LeetCode Hot 100 搜索二维矩阵 II

编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性&#xff1a;每行的元素从左到右升序排列。每列的元素从上到下升序排列。示例 1&#xff1a;输入&#xff1a;matrix [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,13,14,17,24],[…

Windows Edge 播放 H.265 视频指南

目录 &#x1f4cc;前言 一 . 什么是 H.265&#xff08;HEVC&#xff09;&#xff1f; 二、为什么 Edge 默认不能播放 H.265&#xff1f; 三、Edge 播放 H.265 解决方案 1 . 查看显卡是否支持硬解AMD GPU Decoder Device InformationNVIDIA GPU Decoder Device Informat…

线性代数--AI数学基础复习

原文链接&#xff1a;Github-Funny_Mr_Zhi GNN_playground 参考&#xff1a;麻省理工公开课 线性代数 MIT Linear Algebra Chapter1 可以带着问题去读&#xff0c;线性代数到底是什么&#xff0c;矩阵又是什么。尽管深入学习数学需要一种抽离出现实和直观理解的高度抽象思维&…

Cursor配置DeepSeek调用MCP服务实现任务自动化

文章目录1. 任务需求2. 环境准备2.1 Cursor安装2.2 Node.js安装2.3 DeepSeek模型Key申请2.4 高德地图Key申请3. MCP服务配置3.1 Cursor配置Server方式3.1.1全局设置3.1.2 项目级别设置3.2 MCP服务接入3.2.1 高德地图MCP服务3.2.2 Mysql MCP服务3.2.3 FileSystem MCP服务3.2.4 验…

java SpringBoot数据库查询 时间范围查询

exTime的类型为varchar 存储的数据格式为yyy-MM-ddTHH:mm:ss,查询时传进来的时间格式也需要为yyy-MM-ddTHH:mm:ss格式Query(value "SELECT * FROM test_fbep fbep WHERE delFlag 1 " "AND IF(?1 ! AND ?1 IS NOT NULL, fbep.passId ?1, TRUE) " &q…