CS144 lab2 笔记

CS144 lab2 笔记

介绍

lab0中,我们实现了一个ByteStream

lab1中,实现了一个重组字符片段的StreamReassembler,重组收到的字符片段,并且将排序好的字符串退送到ByteStream

lab2中,j将实现一个TCPReceiver,它将在TCP segmentsbyte stream之间进行转换

image-20220123222702799

通过这个图片

  • ackno就是第一个未排序片段的索引,是期望下一个收到的片段索引

  • 第一个未排序片段与流末端索引之间的距离就是window size(TCP窗口)

    the distance between the “first unassembled” index and the “first unacceptable” index.
    This is called the “window size”

Translating between 64-bit indexes and 32-bit seqnos

img

  1. 通过TCP报头我们可以知道,传输过程中的seq是32位的,但我们本地的seq是64位系统下的,所以我们需要将seq(64bit)--->seq(32bit),32位最大值为 232-1,超过这个数字就从0开始

  2. TCP seq 以一个32为随机值初始化:这个目的是为了防止被猜到,以及网络中较早的数据报造成干扰,一端连接中第一个seq就以一个32位的数字初始化,叫做Initial Sequence Number(ISN),之后每个seq/mod 232

  3. 连接开始和结束每个占用一个序列号:除了确保收到所有字节的数据,TCP确保流的开始和结束同样是是可靠的。因此,在TCP中,SYN(流开始)和FIN(流终端)控制标志被分配序列号。都占据一个序列号。 (SYN标志占用的序列号就是ISN。)流中的每个数据字节还占用一个序列号。请记住,SYN和FIN不是流本身的一部分,而不是“字节” —它们代表字节流本身的开始和结束。

这些seq在每个TCP段的头中发送。**绝对序列号:**始终以零开始并且不包装(就是64位),流索引:StreamReassEmbler流中的每个字节的索引,从零开始,64bit,具体见下图:

image-20220123224747548

思路

  • 很显然这种转换不是唯一的——seqno每次增加2322^{32}232值都不变,但是absolute seqno变化。为了确定唯一的结果,我们需要checkpoint,即将可能的结果中距离checkpoint最近的作为最终结果。

  • checkpoint表示最近一次转换求得的absolute seqno,而本次转换出的absolute seqno应该选择与上次值最为接近的那一个。原理是虽然segment不一定按序到达,但几乎不可能出现相邻到达的两个segment序号差值超过INT32_MAX的情况

  • 如果想不出来,就在纸上画一画就能想出来了

实现

//! Transform an "absolute" 64-bit sequence number (zero-indexed) into a WrappingInt32
//! \param n The input absolute 64-bit sequence number
//! \param isn The initial sequence number
WrappingInt32 wrap(uint64_t n, WrappingInt32 isn) { return WrappingInt32(static_cast<uint32_t>(n) + isn.raw_value()); }//! Transform a WrappingInt32 into an "absolute" 64-bit sequence number (zero-indexed)
//! \param n The relative sequence number
//! \param isn The initial sequence number
//! \param checkpoint A recent absolute 64-bit sequence number
//! \returns the 64-bit sequence number that wraps to `n` and is closest to `checkpoint`
//!
//! \note Each of the two streams of the TCP connection has its own ISN. One stream
//! runs from the local TCPSender to the remote TCPReceiver and has one ISN,
//! and the other stream runs from the remote TCPSender to the local TCPReceiver and
//! has a different ISN.
uint64_t unwrap(WrappingInt32 n, WrappingInt32 isn, uint64_t checkpoint) {int32_t interval = n - wrap(checkpoint, isn);int64_t result = checkpoint + interval;if (result >= 0)return result;elsereturn result + (1ul << 32);
}

Implementing the TCP receiver

对于接收端,在这个实验中只需要处理示意图中彩色部分:

image-20220123231716604

在做实验之前最好看一下TCPSegment的相关实现

思路

主要就是参考下图中TCP的过程,将其分为图中三种情况,一一实现即可,错误不需要考虑,将在之后的实验进行处理

image-20220123232228395

segment received()

  • 请设置初始序列号。设置ISN,并且不要忘记使用 。请注意,SYN标志只是标题中的一个标志。相同的段也可以携带数据,甚至可以设置FIN标志。所以,即使受到syn也不能抛弃他的片段以及fin
  • 将任何数据或流终端标记推向StreamReasseMbler。如果FIN标志设置在TCPSegment的标题中,这意味着有效载荷的最后一个字节是整个流的最后一个字节。

ackno()

  • 返回包含接收器尚未知道的第一个字节的序列号的wraxingInt32。这是Window的左边缘。如果尚未设置ISN,则返回一个空可选

window size()

  • 见代码

实现

tcp_receiver.hh

class TCPReceiver {//! Our data structure for re-assembling bytes.StreamReassembler _reassembler;//! The maximum number of bytes we'll store.size_t _capacity;bool _syn {false};WrappingInt32 _isn{0};

tcp_receiver.cc

void TCPReceiver::segment_received(const TCPSegment &seg) {const TCPHeader &_tcp_header = seg.header();/** 不需要考虑很多,直接按照tcp接收端状态转换图写就行,其他情况都可以交给reassembler处理*/if (!_syn)  // 如果未收到过syn{if (!_tcp_header.syn)// 如果包中含有syn就继续,没有就直接返回,抛弃包return;_syn = true;_isn = _tcp_header.seqno;}// ack 期望下一个收到的片段索引uint64_t _ackno = _reassembler.stream_out().bytes_written() + 1;// 计算 sequint64_t _seqno = unwrap(_tcp_header.seqno, _isn, _ackno);// 注意syn也占用seqno,所以别忘了uint64_t _index = _seqno - 1 + static_cast<uint64_t>(_tcp_header.syn);_reassembler.push_substring(seg.payload().copy(), _index, _tcp_header.fin);
}optional<WrappingInt32> TCPReceiver::ackno() const {if (!_syn) // 如果未建立连接,直接返回空return nullopt;uint64_t _ackno = _reassembler.stream_out().bytes_written() + 1;if (_reassembler.stream_out().input_ended())// 如果结束连接,返回的ack要算上sender发来的fin_ackno++;return WrappingInt32(_isn) + _ackno;
}
// 如下
size_t TCPReceiver::window_size() const { return _capacity - _reassembler.stream_out().buffer_size(); }

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

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

相关文章

CS144 计算机网络实验 lab3 笔记

CS144 计算机网络实验 lab3 笔记 介绍 本实验中,我们将会在之前实验的基础上,实现一个TCP sender ----将字节流转换成数据报并发送. TCP协议是一个在不可靠的协议上提供可靠的,流量控制的协议。 我们在本实验中会实现一个TCP发送端&#xff0c;负责将发送端应用层传入的比特…

CS144 lab4 计算机网络实验 笔记

CS144 lab4 计算机网络实验 笔记 介绍 本实验中,我们将组合TCP sender和TCP receiver实现一个完整的TCP connection TCP是全双工连接,所以两方可以同时接收/发送信息,一端随时都有可能接收.发送信息 主要根据上图实现 tcp_connection.cc #include "tcp_connection.hh&…

C# GDI+ 实现图片分隔

1. 概述 有时候我们需要在web页面上显示一张图&#xff0c;比如说一张地图&#xff0c;而这张地图会比较大。这时候如果我们把一张大图分隔成一组小图&#xff0c;那么客户端的显示速度会明显地感觉块。希望阅读本文对你有所帮助。 2. 实现思路 .NET Framework GDI 为我们提…

c/c++面试试题(一)

1.求下面函数的返回值&#xff08;微软&#xff09;int func(x) { int countx 0; while(x) { countx ; x x&(x-1); } return countx; } 假定x 9999。 答案&#xff1a;8思路&#xff1a;将x转化为2进制&#xff0c;看含有的1…

2. Get the codes from GIT

Clone the code from git. Click the “GitEx Clone”. Paste the url into the “Repository to clone”. You can get the route from git repository from it: https://msstash.companydomainname.com/ .Find the project which you want to download and then click the “…

The Ranges Library (2) --- C++20

The Ranges Library (2) — C20 比较std与std::ranges算法 比较一下std::sort和std::ranges::sort std::sort template< class RandomIt > constexpr void sort( RandomIt first, RandomIt last );template< class ExecutionPolicy, class RandomIt > void sor…

WPF中的动画

WPF中的动画 周银辉动画无疑是WPF中最吸引人的特色之一&#xff0c;其可以像Flash一样平滑地播放并与程序逻辑进行很好的交互。这里我们讨论一下故事板。在WPF中我们采用Storyboard&#xf…

[访问系统] Api_Win32_Mac类工具包 (转载)

点击下载 Api_Win32_Mac.zip using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.InteropServices;namespace BaseFunction {class API{[DllImport("kernel32")]//内存public static extern void GlobalM…

constexpr 函数

constexpr 函数 — C 20 constexpr double pi 3.14;constexpr允许你在编译时使用典型的C函数语法进行编程,但这并不意味之constexpr只和编译期有关 constexpr函数可以在编译期运行,也可以在运行时运行 但在以下情况constexpr函数必须在编译期运行: constexpr函数在编译的上…

constexpr和consteval --- C++ 20

constexpr和consteval — C 20 标准库容器和算法库对constexpr 的应用 C20 中大量的算法和容器可以使用constexpr,这意味着你甚至可以再编译期vector<int>进行排序 Algorithms library - cppreference.com 如下: #include <iostream> #include <ranges>…

函数模板(参考《C++ Templates 英文版第二版》)

函数编程(参考《C Templates 英文版第二版》) Chapter 1 函数模板 1.1 一窥函数模板 template<class T> T max(T a, T b) {return b < a ? a : b; }#include "max1.hpp" #include <iostream> #include <string> #include <format>int…

Curiously Recurring Template Pattern奇怪的模板递归 --- C++20

Curiously Recurring Template Pattern 奇怪的模板递归 — C20 我们都知道C有静态多态和动态多态,动态多态通过虚函数表实现,他的缺点就是对效率产生一点点影响 可以用CRTP解决这个问题 我们先举一个动态多态的例子: #include <iostream> using namespace std;class …