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();}
}

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

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

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

相关文章

江协科技51单片机学习- p23 DS1302实时时钟

&#x1f680;write in front&#x1f680; &#x1f50e;大家好&#xff0c;我是黄桃罐头&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流 &#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐️ 留言&#x1f4dd;​…

巴比达内网穿透:深度剖析其在解决远程连接挑战中的技术优势

在信息技术日新月异的今天&#xff0c;远程协作与管理的需求日益增长&#xff0c;但内网环境的隔离性一直是横亘在高效远程操作面前的一道坎。本文将深入探讨一款专为打破此壁垒而生的工具——巴比达内网穿透&#xff0c;如何以其技术创新和高效性能&#xff0c;成为解决远程连…

汽车内饰塑料件光照老化实验箱

塑料件光照老化实验箱概述 塑料件光照老化实验箱&#xff0c;又称为氙灯老化试验箱&#xff0c;是一种模拟自然光照条件下塑料材料老化情况的实验设备。它通过内置的氙灯或其他光源&#xff0c;产生接近自然光的紫外线辐射&#xff0c;以此来加速塑料及其他材料的光老化过程。…

数据挖掘常见算法(分类算法)

K&#xff0d;近邻算法&#xff08;KNN&#xff09; K-近邻分类法的基本思想&#xff1a;通过计算每个训练数据到待分类元组Zu的距离&#xff0c;取和待分类元组距离最近的K个训练数据&#xff0c;K个数据中哪个类别的训练数据占多数&#xff0c;则待分类元组Zu就属于哪个类别…

Python + OpenCV 酷游地址教学V鄋KWK3589

本篇文章汇整了一系列的Python OpenCV 教学&#xff0c;只要按照教学文的顺序阅读和实作&#xff0c;就可以轻松入门OpenCV&#xff0c;并透过OpenCV 实现许多影像相关的创意应用。 接下来我们来介绍OpenCV-- OpenCV 是一个跨平台的电脑视觉函式库( 模组) &#xff0c;可应用…

Python容器 之 字符串--字符串的常用操作方法

1.字符串查找方法 find() 说明&#xff1a;被查找字符是否存在于当前字符串中。 格式&#xff1a;字符串.find(被查找字符) 结果&#xff1a;如果存在则返回第一次出现 被查找字符位置的下标 如果不存在则返回 -1 需求&#xff1a; 1. 现有字符串数据: 我是中国人 2. 请设计程序…

Gavin大咖亲自授课:将大语言模型与直接偏好优化对齐

Gavin大咖亲自授课&#xff1a;将大语言模型与直接偏好优化对齐 Align LLMs with Direct Preference Optimization 直接偏好优化&#xff08; Direct Preference Optimization&#xff09;这绝对是天才性的算法。你会看到数学的巨大力量和巨大价值&#xff0c;你一定会很兴奋和…

【计算机网络期末复习】例题汇总(一)

重点例题选择填空简答题与传输媒体的接口的特性重点 计算机网络的性能指标计算机网络体系结构例题 选择

Linux高并发服务器开发(八)Socket和TCP

文章目录 1 IPV4套接字结构体2 TCP客户端函数 3 TCP服务器流程函数代码粘包 4 三次握手5 四次挥手6 滑动窗口 1 IPV4套接字结构体 2 TCP客户端 特点&#xff1a;出错重传 每次发送数据对方都会回ACK&#xff0c;可靠 tcp是打电话的模型&#xff0c;建立连接 使用连接 关闭连接…

泛微E9开发 根据故障来源新增明细行,并且初始化错误类型

根据故障来源新增明细行&#xff0c;并且初始化错误类型 1、需求说明2、实现方法3、扩展知识点3.1 批量修改字段值或显示属性3.1.1 格式3.1.2 参数3.1.3 演示 3.2 根据字段ID获取字段信息3.2.1 格式3.2.2 参数3.2.3 演示 1、需求说明 用户对出现故障的机器或设备进行判断问题判…

C++进阶 | [4.3] 红黑树

摘要&#xff1a;什么是红黑树&#xff0c;模拟实现红黑树 红黑树 &#xff0c;是一种 二叉搜索树 &#xff0c;但 在每个结点上增加一个存储位表示结点的颜色&#xff0c;可以是 Red 或 Black 。 通过对 任何一条从根到叶子的路径上各个结点着色方式的限制&#xff0c;红黑树…

分享一个在 WinForm 桌面程序中使用进度条展示报表处理进度的例子,提升用户体验

前言 在有些比较消耗时间的业务场景中&#xff0c;比如生成报表等&#xff0c;如果没有在操作的过程中向用户反馈操作进度&#xff0c;会让用户以为程序 “死” 掉了&#xff0c;用户体验非常不好。 WinForm 桌面程序项目与 Console 项目不一样&#xff0c;如果 Console 项目…

【C++】红黑树及其实现

目录 一、红黑树的定义1.为什么提出红黑树&#xff1f;2.红黑树的概念3.红黑树的性质 二、红黑树的实现1.红黑树的结构2.红黑树的插入2.1 uncle为红色2.2 uncle为黑色&#xff0c;且是grandfather的右孩子2.3 uncle为黑色&#xff0c;且是grandfather的左孩子 3.红黑树的验证 4…

虚拟机网络配置(静态网络)

解决问题&#xff1a;VMware中创建centOS虚拟机后使用ifconfig没有ip地址&#xff0c;但我想在主机&#xff08;Windows&#xff09;系统下使用shell连接虚拟机从而方便后续交互。 VMware中编辑->虚拟网络编辑器 &#xff08;注意需要管理员身份不然会无法修改&#xff09;…

PV操作经典例题

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 一、前言&#x1f680;&#x1f680;&#x1f680;二、正文☀️☀️☀️三、总结&#x1f353;&#x1f353;&#x1f353; 一、前言&#x1f680;&#x1f680;&am…

万字长文|下一代系统内存数据加速接口SDXI解读

本文内容分为5章节&#xff0c;总计10535字&#xff0c;内容较多&#xff0c;建议先收藏&#xff01; 1.SDXI技术产生的背景 2.SDXI相比DMA的优势 3.SDXI实现原理与架构 3.1 描述符环原理解读 3.2 上下文管理介绍 3.3 AKey与RKey解读 3.4 错误日志和状态管理 3.5 跨Function访…

ctfshow web入门 sqli-libs web552--web560

web552 宽字节注入 嗯原理我就不讲了&#xff0c;还是有点复杂后面有时间讲讲 总而言之就是用汉字把\的转义作用抵消了然后正常注入即可 ?id-1包 union select 1,2,3--?id-1包union select 1,(select group_concat(table_name) from information_schema.tables where tab…

事过无悔:人生中的释怀之道

在纷繁复杂的人生旅途中&#xff0c;我们常常会面临各种选择。这些选择&#xff0c;如同指引我们前行的路标&#xff0c;有时让我们欣喜&#xff0c;有时让我们遗憾。然而&#xff0c;我渐渐发现&#xff0c;事过无悔&#xff0c;是我们在面对这些选择时最顶级的释怀之道。 首…

MySQL 常见存储引擎详解(一)

本篇主要介绍MySQL中常见的存储引擎。 目录 一、InnoDB引擎 简介 特性 最佳实践 创建InnoDB 存储文件 二、MyISAM存储引擎 简介 特性 创建MyISAM表 存储文件 存储格式 静态格式 动态格式 压缩格式 三、MEMORY存储引擎 简介 特点 创建MEMORY表 存储文件 内…

节点级、系统级、实车级的LIN测试主要差异点

文章目录 前言一、节点级1.前期准备2.测试执行 二、系统级1.前期准备2.测试执行 三、实车级1.前期准备2.测试执行 总结 前言 LIN协议一致性测试主要指的是物理层&#xff08;电阻、电容、电压、地偏移、显隐性电平、频率占空比、位时间等&#xff09;、数据链路层&#xff08;…