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}) absoluteseqnoseqno?ISN(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} checkpoint?231absoluteseqnocheckpoint+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.pswp.cn/web/71516.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/71516.shtml
英文地址,請注明出處:http://en.pswp.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.…