【Linux】网络--传输层--深入理解TCP协议

article/2025/8/26 15:51:34

在这里插入图片描述

个人主页~


深入理解TCP协议

  • 一、TCP数据传输问题
    • 1、发送数据丢包问题---重传机制
      • (一)客户端数据发送丢包
      • (二)服务器确认应答丢包
      • (三)时间间隔问题
    • 2、三次握手问题---奇数次握手
      • (一)验证可靠全双工
      • (二)确定连接成本
  • 二、TCP三次握手问题
  • 三、TCP四次挥手问题
  • 四、流量控制
  • 五、滑动窗口
    • 1、基本概念
    • 2、丢包问题
    • 3、滑动窗口大小
      • 拥塞控制
  • 六、延迟应答
  • 七、粘包问题
  • 八、文件和网络的关系

一、TCP数据传输问题

1、发送数据丢包问题—重传机制

(一)客户端数据发送丢包

在这里插入图片描述
在我们客户端对服务器发送数据的时候,可能会出现丢包的问题,即数据没有到达服务器,此时服务器不会向客户端发送应答报文,客户端在等待了特定的时间后,会认为数据丢失,对已经发送的数据进行补发

这里是因为主机对于发出去的报文是否丢失是无法判定的,所以必须要通过一定的规定来决定是否要进行重传

(二)服务器确认应答丢包

在这里插入图片描述
还有一种情况就是发送数据没有丢包,但是服务器发给客户端的应答报文丢包了,同样的,对于客户端来说上面的情况和下面是一样的,客户端在等待了特定的时间后,会认为数据丢失,对已经发送的数据进行补发。这叫做超时重传

(三)时间间隔问题

最理想的情况下,找到一个最小的时间,保证确认应答在这个时间内返回,但是这个时间的长短随着网络环境的不同会有差异,如果超时时间设的太长,会影响整体的重传效率,如果超时时间设的太短,有可能会频繁发送重复的报文
TCP为了保证无论在任何环境下都能比较高性能的通信,因此会动态计算这个最大超时时间,一般Linux中超时以0.5s为一个单位进行控制,每次判定超时重发的超时时间都是0.5s的整数倍,如果重发一次仍得不到回答,等待2*0.5s,重发n次仍得不到回答,等待0.5*2^ns,以指数形式递增,累计到一定重传次数,TCP会认为网络或者对端主机出现异常,强制关闭连接

2、三次握手问题—奇数次握手

在这里插入图片描述

(一)验证可靠全双工

注意这里验证的是可靠和全双工两个概念,三次握手是最少次数的验证可靠全双工的方式

  • 一次握手:一次握手就不必多说了,只能让服务器知道客户端是就绪的,而客户端对服务器丝毫不知情,此时只能验证客户端可发送报文,服务器可接收报文,并且多个客户端对服务器发起连接会造成SYN洪水问题,即服务器接受大量的各个客户端发来的SYN报文
  • 二次握手:二次握手可以验证客户端发送报文,服务器接收和发送报文,不能验证客户端是否可以接收报文,验证不了全双工
  • 三次握手以及多次握手:三次握手以及多次握手就可以保证双方全双工的通信模式,其中三次握手是代价最小的验证可靠全双工的方式

(二)确定连接成本

三次握手是由客户端发起,最终由客户端应答的连接模式,通过客户端主动发起连接并两次确认(SYNACK),迫使客户端承担连接失败的重试成本,而服务器仅在最终确认后才分配资源,避免了无效连接的资源浪费,从而将连接成本转移至客户端

二、TCP三次握手问题

  • 半连接队列和连接队列:当客户端向服务器发起连接请求时(通过 TCP 协议的三次握手),服务器会维护两个队列来处理这些请求:半连接队列SYN 队列)和全连接队列accept 队列),全连接队列用于存放已经完成三次握手过程的连接服务器接收到客户端的 SYN 包后,会向客户端发送 SYN+ACK 包,并将该连接信息放入半连接队列中,等待客户端的 ACK 包,也就是说,当客户端和服务器完成了 TCP 三次握手,建立了一个有效的连接之后,这个连接就会被放入全连接队列中等待服务器调用accept函数来处理

  • 队列特点

    • 全连接队列有一个最大长度限制,这个限制就是listen函数的第二个参数,它表示全连接队列的最大长度,如果有半连接队列中的节点完成三次握手,当全连接队列未满时,那么该节点脱离半连接队列进入全连接队列,当全连接队列已满时,那么服务器一般会忽略新连接,并且这个参数不能太大也不能太小,因为这个值太大会导致多个客户端连接到服务器上引起的资源减少的问题,太小又会导致服务器同时处理多个任务的能力差
    • 半连接队列不会被服务器长时间维护,因为半连接队列中的连接处于 TCP_SYN_RECV 状态,也就是三次握手中的第二步,这个状态设计目标也是快速完成,而非长期持有
  • 三次握手是下层协议:连接建立成功和上层有没有accept没有任何关系,三次握手是双方操作系统自动完成的,accept只是处理三次握手完成后的动作

三、TCP四次挥手问题

  • TIME_WAIT:不知大家是否会发现一种现象,在我们前面的代码中被绑定的端口号比如8080、8888、9090等,在我们终止进程之后再次绑定会短时间的无法绑定,显示出端口号被占用的错误,实际上,这就是主动断开连接的一方,在四次挥手完成之后要进入TIME_WAIT状态,等待若干时长才会释放,来到CLOSED状态,所以一直占用着端口号,当然也包括ip地址,这里的若干时长指的是两个MSL(TCP报文的最大生存时间),在不同操作系统上的MSL不同
    • 等待两个MSL的原因是:能保证在两个传输方向上的尚未被接收或迟到的报文段都已经消失,否则若服务器立刻重启,可能会收到上个进程迟到的数据,同时在理论上保证最后一个报文可靠到达,假设最后一个ACK丢失,那么服务器会重发一个FIN,这时虽然客户端的进程不在了,但是TCP连接还在,仍可以重发LAST_ACK

四、流量控制

接收端处理数据的速度是有限的,如果发送端发得太快,导致接收端的缓冲区被打满,这个时候如果发送端继续发送就可能造成丢包,因此TCP的流量控制原理就是根据接收端的处理能力,来决定发送端的发送速度

接收端通过报头中的窗口大小字段对自身缓冲区剩余空间向发送端通知,发送端发现接收端的缓冲区的剩余空间变小,它发送数据的速度也慢慢变小,当接收段缓冲区满了,就会将窗口大小设为0,这时发送方不再发送数据,但是需要定期发送一个窗口探测数据段,使接收端把窗口大小告诉发送端

五、滑动窗口

1、基本概念

当我们发送和接收数据时,发送方和接收方一发一收性能极低,一次发送多条数据可以大大的提高性能,因为这样可以把多个段的时间重叠到一起,因为有了滑动窗口区域,我们才实现了一次向对方发送大量的TCP报文,滑动窗口位于发送缓冲区

滑动窗口顾名思义就是一个滑动的窗口,这个窗口的左边是已发送并且对方已确认的数据,窗口中的数据是已发送但对方未确认的数据,窗口的右边是待发送的数据,正常情况下,窗口中的数据被确认后,窗口就会向右移动,如下图所示
在这里插入图片描述
滑动窗口的维护可以用两个指针实现,已发送并且对方已确认的数据,即滑动窗口左边的数据就可以被覆盖掉了,滑动窗口中的数据是需要被维护的,这也实现了我们TCP协议中的信息保护,只要没有收到对方的应答就一直维护刚刚已经发出的报文

2、丢包问题

  • 数据包成功抵达,ACK丢失:我们打个比方,假如我们一下发送了四个报文,然后前3个报文返回的ACK都丢失了,但是因为第4个报文返回了ACK,所以前面的都收到了
    在这里插入图片描述

  • 数据包在发送的过程中丢失:假设我们一下发送六个报文,其中第2个报文在发送过程中丢失了,然后从第3个开始的后面的报文发送到接收端后,接收端返回的ACK都是2001,连续收到三个同样的ACK就会触发重发系统,对数据进行重发,重发以后,接收端返回的ACK就是7001了,因为之前收到的报文都在接收缓冲区中,这种机制被称为快重传高速重发控制),我们的快重传和超时重传一个起到能快速重传的效果,一个起到至少将报文重传的效果
    在这里插入图片描述

3、滑动窗口大小

  • 滑动窗口的大小取决于三个因素,取三者中最小的作为滑动窗口的决定因素,一是接收端接收能力,也就是接收缓冲区还有多少空间,二是发送缓冲区中的数据多少,也就是发送缓冲区未发送的数据还有多少,三就是网络环境,这就与我们下面说的拥塞控制息息相关
  • 整个对于发送缓冲区的控制,包括滑动窗口左右两边以及滑动窗口中的内容,滑动窗口并不是发了数据之后一直向右的,而是通过取模运算的一种环形结构

拥塞控制

  • 网络是大家的网络,在同一局域中,同一时间如果有大量的数据被发送到服务器,会导致网络状态拥塞,此时所有的发送端有一个共同的动作就是感受到网络拥塞的状态后使用慢启动机制,先发少量的数据,探测网络状况,如果状况现在比较好了,就渐渐增多数据
  • 引入一个新的概念:拥塞窗口,发送开始的时候,定义拥塞窗口大小为1,每次收到一个ACK应答时,拥塞窗口加1,每次发送数据包时,将拥塞窗口和接收端主机反馈的窗口大小做对比,取较小的值为实际发送的窗口
  • 慢启动机制:TCP开始启动时,慢启动阈值等于拥塞窗口最大值,每次超时重传时,慢启动阈值会变成原来的一半,同时拥塞窗口置为1,超过阈值前指数增长,慢启动阈值就是指数增长的最大点,超过阈值后进行一次函数单调递增
  • 如果是少量丢包,我们会认为是触发了超时重传,大量丢包,我们就会认为是网络拥塞,当TCP开始通信时,网络吞吐量会逐渐上升,随着网络拥塞,吞吐量会立即下降
    在这里插入图片描述

六、延迟应答

  • 延迟应答的策略也是为了提高性能,假设接收端的缓冲区为100KB,一次接收到50KB的数据,如果立刻应答,窗口大小就是50KB,但如果处理端的处理速度比较快,很快就能把这50KB取走,我们可以稍微等一等,让处理端先把数据取走再往回传窗口大小,所以我们设置一个确定的时间,尽量保证在这一段时间里处理端如果处理速度较快的话能将数据取走又不会很耽误应答,结合我们前面提到的窗口越大,传输速度就会越快,所以能提高传输性能
  • 延迟应答的策略有两种,一种是数量限制,每隔N个包应答一次,另一种是时间限制,每超过最大延迟时间就应答一次

七、粘包问题

  • TCP传输协议是面向字节流的,即发送的数据是没有边界的,是以字节为单位发送的,所以有可能会引发粘包问题,粘包问题就是在TCP 通信中,发送方连续发送的多个独立数据包,在接收方被合并成一个大数据包接收,导致数据边界丢失
  • 解决粘包问题的方法是定长报文、使用特殊字符、使用自描述字段+定长报头、使用自描述字段+特殊字符,即在通过在应用层定制协议,使通信双方可以拿到对应的数据

八、文件和网络的关系

网络本质上也是文件,因为Linux一切皆文件,在网络中,网络套接字与文件描述符相同,读写的接口都是一样的,我们可以用和文件操作一样的操作对网络套接字进行操作
在这里插入图片描述
如上图所示,我们的网络通信实际上也就是进程间通信,前面不多说了,在struct file中有两个指针,其中一个private_data指向网络套接字socket,另一个f_op指向网络相关的方法,其中结构体socket中还有一个struct file类型的指针指向这个file结构体

在结构体socket中还有一个字段是struct sock* sk,其中sock结构体是udp_socktcp_sock的第一个参数,可以通过强制类型转换的方式将sock结构体转为udp_socktcp_socksock结构体中有接受队列struct sk_buff_head sk_receive_queue;和写队列struct sk_buff_head sk_wirte_queue;,其中sk_buff_head是用于管理结构体sk_buff,是多个sk_buff组成链表的头部

struct socket
{//...struct file* file;struct sock* sk;//...
}
struct sock
{struct sk_buff_head sk_receive_queue;//接收队列struct sk_buff_head sk_wirte_queue;//写队列
}
struct sk_buff
{sk_buff_data_t tail;sk_buff_data_t end;unsigned char *head, *data;unsigned int truesize;
}

在这里插入图片描述
headdata 之间的区域主要用于在数据包处理过程中添加协议头部,当数据包在网络协议栈中从上层向下层传递时,每经过一层协议,都需要在数据包的前面添加该层的协议头部,由于 head 位置固定,而 data 指针可以向前移动,因此 headdata 之间的空闲空间就可以用来存放这些新添加的头部信息,每经过一层协议 data 指针就向上向下移动,添加或移除报头


今日分享就到这里了~

在这里插入图片描述


http://www.hkcw.cn/article/YHxLKALDWO.shtml

相关文章

深入理解 SQL 的 JOIN 查询:从基础到高级的第一步

在处理数据库时,我们常常需要从多个表中提取数据。比如想知道一个城市的天气情况,同时又想知道这个城市的具体位置。这就需要将 weather 表和 cities 表结合起来查询。这种操作在 SQL 中被称为 JOIN 查询。 现在看下两种表的情况 1.weather 表&#xff…

【无标题】C++23新特性:支持打印volatile指针

文章目录 前言背景与问题C23的解决方案实现原理使用场景硬件开发多线程调试 总结 前言 在C开发中,volatile关键字常用于修饰变量,以确保编译器不会对这些变量进行优化,从而保证程序能够正确地与硬件交互或处理多线程环境下的特殊变量。然而&…

RPG15.轻攻击

上一篇已经制作了装备和卸下武器 接下来开始做战斗系统 1.先添加Tag ARPG_GRIVITY_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(InputTag_EquipAxe);ARPG_GRIVITY_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(InputTag_UnEquipAxe); ARPG_GRIVITY_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Play…

20250529-C#知识:继承、密封类、密封方法、重写

C#知识:继承、密封类、密封方法、重写 继承是面向对象的三大特性之一,通过继承能够减少重复代码的编写,有助于提升开发效率。 1、继承 C#不同于C,只支持单继承当子类出现与父类同名的成员时,父类成员被隐藏&#xff0…

第30次CCF计算机软件能力认证-1-重复局面

时间限制: 1.0 秒 空间限制: 512 MiB 下载题目目录(样例文件) 题目背景 国际象棋在对局时,同一局面连续或间断出现3次或3次以上,可由任意一方提出和棋。 题目描述 国际象棋每一个局面可以用大小为 88…

【计算机网络】第2章:应用层—DNS

目录 一、PPT 二、总结 DNS(域名系统)详解 (一)DNS核心概念 (二)DNS查询过程(重点❗) (三)DNS资源记录(RR)类型…

[C]基础18.自定义类型:联合和枚举

博客主页:向不悔本篇专栏:[C]您的支持,是我的创作动力。 文章目录 0、总结1、联合体(共用体)1.1 联合体类型的声明1.2 联合体的特点1.3 联合体大小的计算1.4 联合体的应用场景1.5 联合体练习:判断机器字节序…

目标检测预测框置信度(Confidence Score)计算方式

预测框的置信度(Confidence Score)是目标检测模型输出的一个关键部分,它衡量了模型对一个预测框中包含特定类别对象的确定程度。 不同的目标检测模型(如Faster R-CNN、SSD、YOLO、DETR等)在计算置信度时有其特有的机制…

视觉分析开发范例:Puppeteer截图+计算机视觉动态定位

一、选型背景:传统爬虫已无力应对的视觉挑战 在现代互联网环境中,尤其是小红书、抖音、B站等视觉驱动型平台,传统基于 HTML 的爬虫已经难以满足精准数据采集需求: 内容加载由 JS 动态触发,难以直接解析 HTML&#xf…

Java 开发上门家政系统源码:全流程数字化管理,适配家政公司 / 个体户接单派单

家政服务订单管理混乱、人员调度低效、客户留存率低?基于 Java 开发的上门家政系统源码,凭借其强大的稳定性、灵活的扩展性和全流程数字化管理能力,为家政行业提供了一套高效、低成本的解决方案,实现从接单、派单到服务结算的全链…

java24

1.双列集合Map定义 collection和Map都自有contains方法 把实现类对象赋值给接口类对象属于多态的一种,但是这样不能使用实现类里面的特殊方法和重写方法 写好的API里面好像只有数组的打印值是地址值 2.Map遍历方式 Entry是Map接口里面的一个内部接口,所…

VSCode的下载与安装(2025亲测有效)

目录 0 前言1 下载2 安装3 后记 0 前言 丫的,谁懂啊,尝试了各种办法不行的话,我就不得不拿出我的最后绝招了,卸载,重新安装,我经常要重新安装,所以自己写了一个博客,给自己&#xf…

深入了解linux系统—— 库的制作和使用

什么是库? 库,简单来说就是现有的,成熟的代码; 就比如我们使用的C语言标准库,我们经常使用输入scanf和输出printf,都是库里面给我们实现好的,我们可以直接进行服用。 库呢又分为静态库和动态…

VoltAgent 是一个开源 TypeScript 框架,用于构建和编排 AI 代理

​一、软件介绍 文末提供程序和源码下载 VoltAgent 是一个开源 TypeScript 框架,用于构建和编排 AI 代理 二、什么是 VoltAgent? AI 代理框架提供了构建由自主代理提供支持的应用程序所需的基础结构和工具。这些代理通常由大型语言模型 (&am…

弹性公网IP的五大核心优势解析

在云服务架构中,弹性公网IP(EIP)已成为现代企业网络部署的核心组件。与传统固定IP相比,它通过独特的技术机制解决了动态环境下的公网访问难题。以下五大核心优势决定了其不可替代的价值: 一、动态绑定的灵活性 弹性公…

分布式数据库备份实践

在分布式备份中可以采取两种方式进行备份,一种是采用手动编写backup.yml文件进行备份,另外一种是吧备份过程交给备份工具自动执行。如果需要个性化进行备份,建议采用手动编写备份文件方式进行备份。 以下是针对两种备份方式的实践&#xff1a…

社群分享:义乌|杭州电商|店群卖家,私域鱼塘运营的排单系统开源|私域鱼塘运营|返款软件开源

熟悉东哥的朋友都知道,我自己也运营一个电商社群,主要是针对玩私域|鱼塘的电商玩家。 在当前电商环境下,社群分享型电商、店群卖家及私域鱼塘运营者,面临着日益复杂的订单管理和客服调度问题。传统的人工处理不仅效率低…

一键提取Office内图片的工具

软件介绍 OfficeImagesExtractor是一款专门用于提取office文档里面图片的软件。 软件开发 这款软件是由吾爱大佬namejm专门开发的。 软件使用方法 该软件使用起来非常简单。用户只需要把文件拖入到软件里,再设置好保存目录即可。 支持文件格式 这款软件能提取的…

NVIDIA英伟达AI图片视频内容描述总结软件describe-anything整合包

和大家分享一个英伟达联合其他大学开发的一款应用describe-anything,该应用可以通过AI识别分析并详细描述图片视频中指定区域物体内容,我基于最新版制作了免安装一键启动整合包,下载链接在文章末尾。 describe-anything介绍 Describe Anythi…

农村土地承包经营权二轮延包—归户表

"作为二轮延包公示后的一个确认方式,归户表还是要写一下的。归户表跟摸底表很相似,编程方面,用到的python库,摸底表用py-docx多一些,归户表更多用的pywin32,py-docx对于word无依赖,所以摸底…