news 2026/3/28 14:04:25

C/C++ Linux网络编程14 - 传输层TCP协议详解(保证可靠传输)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C/C++ Linux网络编程14 - 传输层TCP协议详解(保证可靠传输)

上篇文章:C/C++ Linux网络编程13 - 传输层TCP协议详解(面向字节流和有连接)-CSDN博客

代码仓库:橘子真甜 (yzc-YZC) - Gitee.com

上篇文章中,我们详细叙述了TCP的面向字节流和连接机制。TCP还有一个特性是可靠传输

目录

一. TCP报头字段说明

1.1 序列号和确认序列号

1.2 16位窗口大小

1.3 标记位和紧急指针

二. 确认应答机制

三. 超时重传机制

四. 流量控制机制

五. 滑动窗口机制

六. 拥塞控制机制

6.1 慢启动

6.2 拥塞避免

6.3 快重传和快恢复

七. 总结


一. TCP报头字段说明

上篇文章中,我们简要提到了TCP报头的格式。

这里介绍一个各个字段的作用。

源端口,目的端口首部长,检验和就不过多介绍。功能和UDP的类似,可以看前两篇文章

1.1 序列号和确认序列号

由于TCP是面向字节流的,如何保证收到的数据的先后顺序是一致的呢?TCP头部的确认序列号就是用于识别某段字节流数据有没有被收到。

比如32位确认序列号是 1234,则表示对方将1234之前的所有数据都收到了。

而32位序号是发送方发送数据使用的,用于标记发送字节流的位置。

总结一下就是:

32位序号:发送方用于标记自己发送数据的位置,是对方报文的确认序号。

可以用于:确保数据顺序,去重,标记字节位置

32位确认信号:接收方接收报文后,若ack = 1234 表示 1234之前的数据都接收完毕了

可以用于:确保数据顺序接收(方便确认和重传),流量控制,支持滑动窗口

1.2 16位窗口大小

讨论一下下面的场景:

发送方发送数据快于接收方:会导致接收方接收缓冲区写满,需要额外的时间来处理缓冲区。这样就会导致双方通信的效率降低。

发送方发送数据小于接收方:会导致对方没有数据处理,浪费时间。也会导致双方的通信收到影响。

所以我们需要控制双方发送接收数据的速度,而16位窗口大小就是用于控制接收数据的速度的。如果对方发送的窗口过大,我就发送更多数据,如果对方发送的窗口较少,我就极少发送的数据。

通信双方通过交换窗口大小来获取对方接收数据的能力,从而调整发送数据的速度。16位窗口大小是流量控制的基础。

1.3 标记位和紧急指针

TCP报文是有不同类型的,通过标记位来区分不同的TCP报文。

SYN:表示这个报文是用于握手请求的。

FIN:表示这个报文是用于挥手请求的。

ACK:表示这个报文是一个确认报文

PSH:push的意思,如果对方接收缓冲区满了就会发送PSH报文催促对方上层快点取走数据。当然也能用于告诉对方立即交付数据

对方看到psh报文后可以立即将数据推送到上层,当然也能直接忽略

RST:复位报文,要求对方重新建立连接。比如我们的连接异常断开了,重新连上后发现对方还在向我发送数据。此时就会发送RST报文告诉对方连接异常断开,需要重新建立连接

URG:紧急报文,TCP的数据报文是按顺序接收的。如果有紧急数据需要发送咋办(比如需要快速判断对方的状态)?

将URG置1就表示有紧急数据发送,对方发现一个紧急报文后就使用报头的紧急指针获取数据中的紧急数据。这个数据也称为带外数据。

接收方什么时候去读取这个紧急指针的数据呢?应用层recv或者send的最后一个参数标志位就是用于读取发送带外数据

二. 确认应答机制

确认应答机制是基于序列号和确认号实现的。当接收对方是数据X之后,我就需要向对方发送确认序号X+1表示之前的X数据都接收到来。

三. 超时重传机制

超时重传机制是TCP用于处理网络丢包问题的。如果发送一个TCP数据报之后,如果一段时间内没有接收到对方的响应。就会默认这个数据丢失了,发送方就会重新发送一个报文。

有两种情况:

1 发送方发送的包丢失了,接收方没有收到

2 接收方接收了发送方的包,但是接收方返回的响应丢失了

两种情况发送方都会进行重传。

思考一下:

1 tcp怎么知道自己发送的数据有没有丢失?

tcp其实并不知道自己的发送数据有没有丢失,只是一段时间内没有收到响应就会进行重传。(即便这个报文还在网络中)

2 既如此,对方不会收到多个相同的报文吗?对方如何处理?

通过序列号来进行去重。这样就能保证同一个数据只会接收一次

3 TCP如何维持自己发送的数据用于重传呢?

维持在发送缓冲区,通过滑动窗口机制处理

4 TCP如何确认超时重传的时间?如果对应一直不应答呢?

由于网络传输的速度是有波动的,如果重传过快,会浪费时间,重传过慢,会导致对方迟迟接收不到数据。所以TCP以500ms,2*500ms依次向对方重传,如果长时间(2MSL)没有收到对方的回应,就会关闭连接。

四. 流量控制机制

TCP报头就介绍了,TCP通过16位窗口来进行流量控制。根据对方发送过来的窗口大小来调整发送数据的数量。从而提高双方通信的效率。

通信双方在三次握手时候其实就第一次交换了互相的窗口大小,后续会定时的发送窗口探测报文用于确定双方接收数据的能力从而调整发送数据的多少。当接收缓冲区的数据被上层取走之后就会更新自己的窗口大小。

TCP首部后面的40字节选项中,包含一个字段M,实际窗口大小是窗口字段左移M位

五. 滑动窗口机制

TCP发送报文的时候并不是一个一个发送的,而是连续发送很多报文,连续处理应答。既如此,TCP如何并发处理这些报文?(即处理确认应答,超时重传,流量控制

观察上面的滑动窗口。

已确认用于: 确认应答

只要接收到对方的应答,snd.una指针就会向右移动

已发送未确认用于: 超时重传

如果发现snd.una和snd.nxt中有数据迟迟没有应答,就会进行重传

可发送用于: 流量控制

我方只要数据,snd.nxt就会向右移动。接收到对方发送的窗口大小后就会移动snd.wnd表示对方的窗口更大,我也能发送更多数据。

所以说:滑动窗户是确认应答,超时重传,流量控制的基础。

在内核中,滑动窗口本质是一个环形结构,肯定有人放数据,有人拿数据,所以不会出现越界问题,越界了取模即可

六. 拥塞控制机制

拥塞控制是用于控制网络通信效率的机制。比如我们client发送了10000个报文,丢包了10个,这是正常的。假如丢掉了99990个呢?明显是网络出现了问题,此时就要执行拥塞控制用于保证整个网络通信的效率。

6.1 慢启动

慢启动是指:通信前期,先少量发送数据,然后根据网络状态发送数据。并且以指数增长。TCP中有一个拥塞窗口cwnd。每当收到一个ack之后,这个cwnd就会加1。每一次传输轮次cwnd就会翻倍。

通过慢启动,我们就能够尽快让网络恢复正常的通信。

注意:网络有一个拥塞窗口,根据对方16位窗口会有一个对方接受能力的窗口。滑动窗口 = min(拥塞窗口,对端发送的窗口)。

6.2 拥塞避免

由于慢启动是指数增长的,若干轮次后cwnd值会很大,导致所有进程发送数据过快。从而导致网络拥塞。为了避免cwnd快速增长导致网络阻塞,需要进行拥塞避免。

当cwnd拥塞窗口到达我们设置的阈值ssthresh就会执行拥塞避免算法。此时每一个轮次不再是2倍增长了,而是线性增长。

这样就能避免拥塞窗口增加过快导致网络堵塞

6.3 快重传和快恢复

当接收方收到三个重复的ack之后,表示这个网络已经很拥塞了(对方由于超时进行重传,重传了3个ack都遗留在网络中,然后连续到达对方,你说是不是非常堵塞)。此时就需要执行快重传和快恢复。

即将cwnd进行乘法减少,一般是*1/2并且设置好新的阈值ssthresh,然后继续执行拥塞避免。这样cwnd就会变小,整个网络的发送速度就会变小,让网络尽快恢复

这样我们就能实现网络通信的同时保证整个网络传输的效率。

七. 总结

TCP通过确认应答机制保证数据被对方顺序接收不重复,通过超时重传机制保证数据不会丢失,通过流量控制保证双方能够以最高效率收发数据,通过滑动窗口机制来支撑前三大机制,通过拥塞控制来保证双方通信的同时确保整个网络通信的效率

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/8 11:55:58

解锁网页视频下载新姿势:VideoDownloadHelper全攻略

解锁网页视频下载新姿势:VideoDownloadHelper全攻略 【免费下载链接】VideoDownloadHelper Chrome Extension to Help Download Video for Some Video Sites. 项目地址: https://gitcode.com/gh_mirrors/vi/VideoDownloadHelper 想保存网页上的精彩视频却无从…

作者头像 李华
网站建设 2026/3/23 10:41:18

局域网设备发现利器:arp-scan深度使用指南

局域网设备发现利器:arp-scan深度使用指南 【免费下载链接】arp-scan The ARP Scanner 项目地址: https://gitcode.com/gh_mirrors/ar/arp-scan 在网络管理和安全运维中,快速准确地发现局域网内的活跃设备是一项基础且重要的工作。传统的ping扫描…

作者头像 李华
网站建设 2026/3/28 8:12:16

如何用layerdivider实现一键智能图像分层?5分钟快速上手教程

如何用layerdivider实现一键智能图像分层?5分钟快速上手教程 【免费下载链接】layerdivider A tool to divide a single illustration into a layered structure. 项目地址: https://gitcode.com/gh_mirrors/la/layerdivider 还在为复杂的图像分层工作而烦恼…

作者头像 李华
网站建设 2026/3/18 12:05:30

css-Echarts图表tooltip / label文本过长 超出屏幕边缘或容器范围

1.tooltip 在靠近浏览器边缘时,部分内容看不见1.1实际场景文本过长或者Echarts刚好处于可视屏幕边缘导致超出的提示文本被截取。1.2tooltip解决方法设置确保tooltip不受父容器限制appendToBody: true,设置让 tooltip 始终限制在视口内,自动调整位置confi…

作者头像 李华
网站建设 2026/3/23 5:55:24

HS2-HF_Patch终极指南:快速解锁HoneySelect2完整功能

HS2-HF_Patch终极指南:快速解锁HoneySelect2完整功能 【免费下载链接】HS2-HF_Patch Automatically translate, uncensor and update HoneySelect2! 项目地址: https://gitcode.com/gh_mirrors/hs/HS2-HF_Patch 想要彻底提升HoneySelect2游戏体验吗&#xff…

作者头像 李华
网站建设 2026/3/25 14:17:43

三步快速制作Windows 11精简系统:新手也能轻松上手

三步快速制作Windows 11精简系统:新手也能轻松上手 【免费下载链接】tiny11builder Scripts to build a trimmed-down Windows 11 image. 项目地址: https://gitcode.com/GitHub_Trending/ti/tiny11builder 你的Windows 11系统是否运行缓慢?老旧电…

作者头像 李华