当前位置: 首页 > news >正文

CS144 Lab3 TCPSender复盘

一.基础概念

1.TCPSender在TCPSocket中的地位与作用

        

        Lab0中实现了基于内存模拟的流控制-字节流(ByteStream),底层使用std::deque实现,根据最大容量Capacity进行容量控制。个人理解它相当于应用层的输入输出缓存区,用户依托Socket发送数据,读取数据。都要先将数据推入缓存区中,例如使用TCP发送数据,用户需要先将数据推入ByteStream中,TCPSender根据滑动窗口当前长度从ByteStream中读取一定数量的数据,之后再进行协议封装,最后推入发送队列中。TCPSender就是执行bytestream到Tcpsegment的工具。值得注意的是这个转换过程应该是自动执行的,且存在滑动窗口流量控制与超时重传机制。LAB4中将会实现TCPConnection他包括TCPSender与TCPReceiver。

        从图中知道bytestream需要转换为TCPSegment需要添加协议头,添加序列号,SYN,payload以及FIN标志位。根据接收端接收到的ackno与window_size确定滑动窗口长度进行流量控制。故而要实现TCPSender时,可发送的数据范围由接收端给出的滑动窗口长度决定。协议头的标志位由当前TCPSender的状态决定。

2.何为端到端模型

        Lab3原文如下:

        TCP is a protocol that reliably conveys a pair of flow-controlled byte streams (one in each
direction) over unreliable datagrams. Two parties participate in the TCP connection, and
each party acts as both “sender” (of its own outgoing byte-stream) and “receiver” (of an
incoming byte-stream) at the same time. The two parties are called the “endpoints” of the
connection, or the “peers.

        端到端是网络连接。 网络要通信,必须建立连接,不管有多远,中间有多少机器,都必须在两头(源和目的)间建立连接,一旦连接建立起来,就说已经是端到端连接了,即端到端是逻辑链路,这条路可能经过了很复杂的物理路线,但两端主机不管,只认为是有两端的连接,而且一旦通信完成,这个连接就释放了,物理线路可能又被别的应用用来建立连接了。简而言之,端到端的通信只要要处理好对应层内的协议就好了,且两端需要对等,协议需要具备普适性。一切优化更改都需要在其上一层进行,本层只负责本层的事务。我们要保证两个端点的行为一致性。

        It’s important to remember that the receiver can be any implementation of a valid TCP receiver—it won’t necessarily be your own TCPReceiver. One of the valuable things about Internet standards is how they establish a common language between endpoints that may otherwise act very differently.

3.TCP协议头格式

        TCPSender负责组装的TCPSegment格式见上图,发送端主要关注其中蓝色部分即可。序列号,FIN以及SYN标志与载荷数据。相对应的接收端需要关注红色部分。

3.ARQ

        The basic principle is to send whatever the receiver will allow us to send (filling the window), and keep retransmitting until the receiver acknowledges each segment. This is called “automatic repeat request” (ARQ). The sender divides the byte stream up into segments and sends them, as much as the receiver’s window allows.

4.TCP如何知道消失丢失(超时重传机制)

        TCPSender在发送消失时,会对已经发送的Segment进行一个缓存备份,我得TCPSender实现中使用了一个FIFO队列进行管理。只有当确认号大于缓存区中Segment的序列号时才进行出队操作。总而言之,我们追踪了滑动窗口发送的每一个Segment的序列号与其内容。通过确认号与序列号以及超时时间RTO来判断数据是否丢失。是否选择重传。

LAB3原文:

 

        需要注意的是如果超时事件发生且窗口长度非0,需要将RTO时间加倍,这是因为在窗长非0时,出现了数据丢失那么当前网络拥塞较为严重,为了避免快速重传导致网络负载加倍,可以降低重传速率。

        超时重传定时器的状态在RFC官方文档中有详细说明如下所示:

这里面有几个坑: 

 1.重传计时器在窗口发送时如果没有启动则会重新启动。这里注意并不是每发送一个数据包就启动一次定时器,对每一个数据包进行计时开销是极其大的。启动定时器是为了对存入重传缓冲区的数据进行计时,如果重传缓冲区空了就要关闭计时器,发送时将数据压入缓冲区,这时如果定时器未启动则启动定时器。

2.当收到新的ACK序号(必须大于之前的ACK序号),会进行定时器更新,具体为清除重传计数,恢复RTO时间。清除缓存区已经确认的数据。

3.如果重传事件发生且窗长大于0,那么必须使RTO加倍。

        总结一下定时器有三种状态,分别为启动、停止、超时。只有在新数据推入且定时器未开启的时候会启动定时器,只有在重传缓冲区没有数据时会关闭定时器,超时发生时如果窗长大于0那么RTO必须加倍。立即定时器的三个状态时Lab3最重要的一点。

二.具体实现

1.TCP发送状态转移

        要完成Lab3需要很好的理解下图,理解了发送的状态转移有助于在写发送窗口时,理清楚条件设置,如下所示:

CLOSED:此时未发送SYN同步标志,如果在这个状态那么发送SYN

SYN_SENT:此时已经发送SYN但是没有收到ACK这时要做的就是等待

SYN_ACKED1:此时收到ACK可以正常收发数据,根据窗口大小划分数据包,尽可能向发送队列写入数据

SYN_ACKED2:此时发送stream已经到达EOF但是FIN还未发送,需要发送FIN

发送了FIN后,窗口将不在发送新数据,此时应该保证fill_window()函数不做任何事情。具体代码实现如下:

void TCPSender::fill_window()
{// CLOSED (waiting for stream to begin no SYN sent)if (next_seqno_absolute() == 0){// send SYN_send_segment("", true);return;}// SYN_SEND (stream started but nothing acknowledged)else if (next_seqno_absolute() > 0&& next_seqno_absolute() == bytes_in_flight()){return;}size_t cur_window_size = (_window_size == 0) ? 1 : _window_size;while (cur_window_size > bytes_in_flight()){// SYN_ACKED (stream ongoing)if (next_seqno_absolute() > bytes_in_flight() && !stream_in().eof()){// flag for send successbool success_send = false;size_t payload_size = min(TCPConfig::MAX_PAYLOAD_SIZE,cur_window_size - bytes_in_flight());string payload      = move(_stream.read(payload_size));// stream reached EOF and  remaining window size can insert FIN flagif (stream_in().eof()&& cur_window_size - bytes_in_flight() - payload.size() > 0)success_send = _send_segment(move(payload), false, true);elsesuccess_send = _send_segment(move(payload));// Nothing to send cause segment length is zore,break.if (!success_send) break;}else if (stream_in().eof()){// SYN_ACK (stream ongoing, stream has reached EOF, but FIN flag hasn't been sent yet)if (next_seqno_absolute() < stream_in().bytes_written() + 2){_send_segment("", false, true);}else// FIN_SENTbreak;}}
}

 2.ack接收部分

        最难的发送部分实现完毕这个较为简单

//! \param ackno The remote receiver's ackno (acknowledgment number)
//! \param window_size The remote receiver's advertised window size
void TCPSender::ack_received(const WrappingInt32 ackno, const uint16_t window_size)
{// update window size_window_size = window_size;// get 64-bit absolute acknouint64_t abs_ackno = unwrap(ackno, _isn, _last_ackno);// if something impossible returnif (abs_ackno > next_seqno_absolute()) return;// if ackno is new ack, check retrans bufferif (abs_ackno > _last_ackno){// update new 64-bit ackno_last_ackno = abs_ackno;while (!_flight_buffer.empty()){const TCPSegment &seg = _flight_buffer.front();if (seg.header().seqno.raw_value() + seg.length_in_sequence_space()<= ackno.raw_value())_flight_buffer.pop();elsebreak;}// update timer setting_consecutive_retransmissions_count = 0;_rto                               = _initial_retransmission_timeout;if (!_flight_buffer.empty())_timer.start(_rto);else_timer.stop();}fill_window();
}

3.重传部分

//! \param[in] ms_since_last_tick the number of milliseconds since the last call to this method
void TCPSender::tick(const size_t ms_since_last_tick)
{// timer elapse_timer.tick(ms_since_last_tick);// if timer out and retrans buffer is not emptyif (_timer.is_expired() && !_flight_buffer.empty()){// retrans_segments_out.push(_flight_buffer.front());// window size has odd cause of internet's bad status, double RTOif (_window_size > 0){_rto *= 2;++_consecutive_retransmissions_count;//std::cout << _consecutive_retransmissions_count << std::endl;}_timer.start(_rto);}else if (_flight_buffer.empty()){_timer.stop();}
}

个人复盘请勿传播,引用。 

相关文章:

CS144 Lab3 TCPSender复盘

一.基础概念 1.TCPSender在TCPSocket中的地位与作用 Lab0中实现了基于内存模拟的流控制-字节流&#xff08;ByteStream&#xff09;&#xff0c;底层使用std::deque实现&#xff0c;根据最大容量Capacity进行容量控制。个人理解它相当于应用层的输入输出缓存区&#xff0c;用户…...

建筑可视化中使用云渲染的几大理由

在建筑行业中&#xff0c;可视化技术已成为不可或缺的一部分。无论是设计方案的展示、施工进度的模拟&#xff0c;还是最终效果的呈现&#xff0c;建筑可视化都发挥着至关重要的作用。 建筑可视化是指通过计算机技术和图形学算法&#xff0c;将建筑设计、规划和施工过程中的数据…...

Python数据可视化-地图可视化

1.首先绘制实现数据可视化的思维导图 具体要实现什么功能-怎么处理&#xff0c;先把思路写好 数据来源&#xff1a; 爬取的数据 运行结果&#xff1a; 部分代码&#xff1a; 完整代码请在下方↓↓↓&#x1f447;获取 转载请注明出处&#xff01;...

leetcode 动态规划(基础版)单词拆分

题目&#xff1a; 题解&#xff1a; 一种可行的dp做法是基于完全背包问题&#xff0c;将s看成是一个背包&#xff0c;wordDict看作是物品&#xff0c;然后往s中放入物品判断最终是否可以变为给定的s即可。这道题和上一题都用到了在dp如何枚举连续子串和状态表示&#xff1a;枚…...

Ubuntu/Linux调试安装南京来可CAN卡

准备好USB rules文件和can driver文件备用! 必做&#xff1a;放置USB rules文件到对应位置处理权限问题 而后&#xff1a;安装内核driver并编译。需求众多依赖编译环境&#xff0c;视情况安装填补。如GCC,G,make等等 进入对应64bit文件夹中&#xff0c;添加权限&#xff0c;执…...

vue2+TS获取到数据后自动叫号写法

1.父组件写法 初始化&#xff1a; //引入子组件 <odialog ref"odialogRef" onSure"onSurea"></odialog> //子传父private onSurea() {// 初始化信息/重新叫号来的数据this.initTabelData()setTimeout(() > {// 播放声音的数据this.search…...

28、架构-边界:微服务的粒度

微服务的粒度 在设计微服务架构时&#xff0c;确定微服务的粒度是一个关键问题。粒度过大或过小都会带来不同的问题&#xff0c;因此需要找到合理的粒度来划分微服务。下面详细探讨微服务粒度的合理范围及其影响因素。 1. 微服务粒度的上下界 微服务的粒度不应该只有唯一正确…...

开源API网关-ApacheShenYu首次按照启动遇到的问题

一.背景 公司有API网关产品需求&#xff0c;希望有图形化的后台管理功能。看到了ApacheShenYu&#xff0c;作为Apache的顶级项目&#xff0c;直接认可了。首先&#xff0c;感谢各位大神的付出&#xff0c;初步看这个项目是国内大厂中的大神创立的&#xff0c;在此表示膜拜&…...

uniapp获取证书秘钥、Android App备案获取公钥、签名MD5值

一、 uniapp获取证书秘钥 打开uniapp开发者中心下载证书打开cmd输入以下这段代码&#xff0c;下载提供查看到的密钥证书密码就可以了&#xff01;下载证书在 java 环境下运行才可以 // your_alias 换成 证书详情中的别名&#xff0c;your_keystore.keystore 改成自己的证书文件…...

QT 如何储存多种数据类型(QVariant )

QVariant 是 Qt 框架中用于存储各种数据类型的类。它提供了一个强大的类型系统&#xff0c;允许你在运行时存储和检索多种类型的数据&#xff0c;而不需要在编译时确定类型。QVariant 的主要优点在于它的灵活性和通用性&#xff0c;这使得它在 Qt 的很多组件和机制中都被广泛使…...

持续总结中!2024年面试必问的操作系统面试题(九)

上一篇地址&#xff1a;持续总结中&#xff01;2024年面试必问的操作系统面试题&#xff08;八&#xff09;-CSDN博客 十七、解释什么是操作系统的安全性和它的重要性。 操作系统的安全性&#xff08;Operating System Security&#xff09;是指操作系统采取的一系列措施来保…...

操作系统入门 -- 文件管理

操作系统入门 – 文件管理 1.文件管理概述 1.1 文件系统基本功能 目前&#xff0c;计算机内存的容量依然有限&#xff0c;并且其特性决定了数据无法长时间保存&#xff0c;因此把执行的数据以文件形式保存在外存中&#xff0c;等到需要使用时再调入内存。所以&#xff0c;操…...

由浅入深,走进深度学习(2)

今天分享的学习内容主要就是神经网络里面的知识啦&#xff0c;用到的框架就是torch 在这里我也是对自己做一个学习记录&#xff0c;如果不符合大家的口味&#xff0c;大家划走就可以啦 可能没有什么文字或者原理上的讲解&#xff0c;基本上都是代码&#xff0c;但是我还是想说…...

【Python Tips】创建自己的函数包并安装进Anaconda,像引入标准包一样直接import导入

目录 一、引言 二、方法步骤 步骤一&#xff1a;创建包目录结构 步骤二&#xff1a;配置__init__.py文件 步骤三&#xff1a;文件夹外配置setup.py文件 步骤四&#xff1a;终端Pip安装 三、结尾 一、引言 在编写项目代码的时候&#xff0c;有些自定义功能的函数是可以复用的。…...

【Python机器学习实战】 | 基于支持向量机(Support Vector Machine, SVM)进行分类和回归任务分析

&#x1f3a9; 欢迎来到技术探索的奇幻世界&#x1f468;‍&#x1f4bb; &#x1f4dc; 个人主页&#xff1a;一伦明悦-CSDN博客 ✍&#x1f3fb; 作者简介&#xff1a; C软件开发、Python机器学习爱好者 &#x1f5e3;️ 互动与支持&#xff1a;&#x1f4ac;评论 &…...

备份和还原

stai和dnta snat&#xff1a;源地址转换 内网---外网 内网ip转换成可以访问外网的ip 内网的多个主机可以使用一个有效的公网ip地址访问外部网络 DNAT&#xff1a;目的地址转发 外部用户&#xff0c;可以通过一个公网地址访问服务内部的私网服务。 私网的ip和公网ip做一个…...

Java数组的初始化方法

Java数组的初始化方法 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;在Java编程中&#xff0c;数组是一种非常基础也非常重要的数据结构&#xff0c;它能够存储…...

通过分离有色和无色pdf页面减少打印费

前言 该工具是我认识的一位中科大的大佬在本科毕业的时候做的一个小工具&#xff0c;去打印店打印全彩的毕业论文的话会比较贵&#xff0c;他想到有没有一种方案可以实现有彩色页面的pdf和没有彩色页面的pdf分开打印&#xff0c;前者打印彩色&#xff0c;后者打印黑白&#xf…...

c语言--指针

前言 欢迎来到我的博客 个人主页:北岭敲键盘的荒漠猫-CSDN博客 本文整理c语言中指针的相关知识点。 指针概念 指针存储的就是数据的地址。 直观理解: 李华家是北洋路130号1单元101 用变量处理数据: 我们去李华家拿数据。 用指针处理数据: 我们去北洋路130号1单元101拿数据…...

python-九九乘法表(对齐式1)

[题目描述] 输出九九乘法表&#xff0c;输出格式见样例。输入格式&#xff1a; 无输出格式&#xff1a; 输出乘法表&#xff0c;对齐方式见样例输出。样例输入 无样例输出 来源/分类&#xff08;难度系数&#xff1a;一星&#xff09; 完整代码展示&#xff1a; #对齐式1 a[] …...

[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解

突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 ​安全措施依赖问题​ GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件

在选煤厂、化工厂、钢铁厂等过程生产型企业&#xff0c;其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进&#xff0c;需提前预防假检、错检、漏检&#xff0c;推动智慧生产运维系统数据的流动和现场赋能应用。同时&#xff0c;…...

高等数学(下)题型笔记(八)空间解析几何与向量代数

目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...

【C语言练习】080. 使用C语言实现简单的数据库操作

080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...

C++ 求圆面积的程序(Program to find area of a circle)

给定半径r&#xff0c;求圆的面积。圆的面积应精确到小数点后5位。 例子&#xff1a; 输入&#xff1a;r 5 输出&#xff1a;78.53982 解释&#xff1a;由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982&#xff0c;因为我们只保留小数点后 5 位数字。 输…...

今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存

文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)

本期内容并不是很难&#xff0c;相信大家会学的很愉快&#xff0c;当然对于有后端基础的朋友来说&#xff0c;本期内容更加容易了解&#xff0c;当然没有基础的也别担心&#xff0c;本期内容会详细解释有关内容 本期用到的软件&#xff1a;yakit&#xff08;因为经过之前好多期…...

Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信

文章目录 Linux C语言网络编程详细入门教程&#xff1a;如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket&#xff08;服务端和客户端都要&#xff09;2. 绑定本地地址和端口&#x…...

C++.OpenGL (20/64)混合(Blending)

混合(Blending) 透明效果核心原理 #mermaid-svg-SWG0UzVfJms7Sm3e {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-icon{fill:#552222;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-text{fill…...

Webpack性能优化:构建速度与体积优化策略

一、构建速度优化 1、​​升级Webpack和Node.js​​ ​​优化效果​​&#xff1a;Webpack 4比Webpack 3构建时间降低60%-98%。​​原因​​&#xff1a; V8引擎优化&#xff08;for of替代forEach、Map/Set替代Object&#xff09;。默认使用更快的md4哈希算法。AST直接从Loa…...