news 2026/9/28 3:04:35

TCP十大核心机制详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
TCP十大核心机制详解

上篇文章,我为大家介绍和演示了关于 UDP 和 TCP 两个协议的网络编程,两个协议的网络编程还是有一定的区别,我个人感觉 TCP 的网络编程会比 UDP 的复杂不少,也更需要我们去理解,并且熟练地掌握。

这篇文章,我将为大家介绍关于 TCP 协议中的十大核心机制。

TCP 的特点:有连接,可靠传输,面向字节流,全双工

1. TCP 报文段首部格式解析

2. 十大核心机制

1.)确认应答

2.)超时重传

3.)连接管理

4.)滑动窗口

5.)流量控制

6.)拥塞控制

7.)延时应答

8.)捎带应答

9.)面向字节流

10.)异常情况

TCP 报文段首部格式解析

在讲解十个核心机制之前,我们先对这张表进行一个大概的了解

16位源端口号:发送方应用程序的端口号,告诉接收方我是谁????

16位目的端口号:接收方应用程序的端口号,告诉网络要把数据传输给谁????

32位序列号:数据包的编号,TCP将一个大的数据拆分成很多个小块进行发送,这个序列号

给数据块排队使用,接收方收到乱序的包后,可以根据这个序号把它们重新拼

成正确的顺序。

32位确认序列号:期望下一个收到字节的序列号,这是接收方给发送方的反馈,意思是“在这

个序号之前的数据我都收到了,请发下一个”。它是TCP可靠传输的核心。

4位首部长度:表示TCP头部有多长,告诉接收方数据从哪里开始读取。图中右侧标注的

“20 字节”指的是标准头部的最小长度。

保留(6位):暂时不需要设置,设置为0。这个是吸取了UDP的教训

URG (Urgent):紧急指针有效,表示包里有紧急数据,需要优先处理。

ACK (Acknowledgment):确认序号有效。连接建立后,所有传送的报文段都必须把ACK置为1。

PSH (Push):提示接收方尽快把数据交给应用程序,不要在缓存里赖着。

RST (Reset):连接出错,要求复位(重置)连接。

SYN (Synchronize):非常重要。用于发起一个新连接。我们在“三次握手”建立连接时主要看这个标志。

FIN (Finish):结束连接。表示“我说完了,我要挂电话了”。

16位窗口大小:接收方告诉发送方,我现在还可以接收多少数据,流量控制。如果接收方处

理不过来,窗口大小变小,发送方就会减慢发送速度,防止把接收方“撑死”。

16位校验和:用于校验数据在传输的过程中是否损坏,接收方收到数据后会算一遍,如果算

出来的结果和这个值不一样,说明数据出错了(比如路上被干扰了),这个包

就会被丢弃。

16位紧急指针:只有当 URG 标志为 1 时才有效。它告诉系统紧急数据在哪里结束???

十大核心机制

1.)确认应答(TCP可靠传输的核心机制)

但是在网络传输的过程中,可能会出现 “先发后至” 的情况,比如网络卡断了一下,发送方发送了俩条信息,我这边可能先收到发送方最后发来的那一条信息,然后才收到发送方最早发送过来的信息,这样信息的含义就可能会出现错误~~~

此时TCP报文段首部格式中有32位序列号和32位确认序列号

32位序列号:针对传输的数据进行编号

32位确认序列号:给ACK报文使用,关联当前这个ACK是应答哪个数据的

32为确认序列号有俩种理解方式:

1.从1001之前的数据,我已经接收到了

2.对方正在想你索要1001之后的数据

应答报文时一种特殊的报文,通常没有载荷,并且在报头的标志位中,将ACK设置为1

总结一下什么叫做可靠性???

什么是可靠性 --> 发送出去的信息,发送方能知道接收方是否接收到了

靠什么做到 ---> 确认应答

如何实现 ---> 发送方发送数据给接收方,接收方接收到数据并且返回一个应答报文

可能出现的问题 ---> 先发后至

如何解决先发后至问题 ---> 通过序列号和确认序列号解决

2.)超时重传

在网络传输的过程中,可能会出现丢包的概率情况,是无法避免的

当发送方发送一个数据,但迟迟没有接收到接收方返回的ACK,这时发送方可能会意识到可能是数据丢了,所以会选择在发送一次数据

但是如果是ACK丢包了,那么也会导致发送方发送俩分同样的数据过来,这时,如果这俩份数据是扣款数据,难道会扣款俩次吗????不会的,接收方知道我已经接收到的数据的序列号范围,如果发现新收到的数据已经在序列号的范围内,说明这个数据已经接受过了,就会将重复的数据丢弃

所以TCP不仅仅解决了可靠传输问题,还解决了数据的传输顺序问题,数据重复传输的问题

但是超时重传的重传也并不是无限次数的重传,如果连续传输多次都没有达到对方,说明可能出现了非常严重的网络故障问题,从而放弃对TCP的连接(直接将对方保留的信息删除)

因为网络故障,如果一直重传也没有任何意义,没必要消耗大量的资源和时间~~~

3.)连接管理

连接管理分为俩部分:

1.建立连接(三次握手)

2.断开连接(四次挥手)

这个核心机制我会单独出一篇文章讲讲滴~~~~

4.)滑动窗口(提高效率)

引入滑动窗口是为了提高效率,因为TCP为了确保可靠连接,肯定多多少少会损失一定的效率

滑动窗口的本质其实就是:批量发送,批量等待ACK

窗口大小越大,批量传输的数据越多,整体的传输效率越高~~~

当滑动窗口 “丢包” 该如何处理呢???

ACK丢失的情况就不需要做任何的处理!!因为ACK的确认序号后,后一个ACK可以包含前一个

但是如果是数据丢失,那么服务器就会一直向客户端索要丢失的数据,直到客户端反应过来,然后重新发送丢失的数据,服务器才停止索要

要注意:服务器是会记录哪些数据已经接收到了,哪些数据是丢失的,然后就会一直向客户端索要丢失了的那段数据!!!

这个机制称之为:快速重传

5.)流量控制(保证可靠性传输)

当滑动窗口传输的数据越大,传输的效率也就越大,如果窗口特别的大,是否可以呢?

当然不行,如果传输的特别快,接收方可能就处理不过来,就可能照成接收方丢包的情况

流量控制就是针对滑动窗口的大小进行控制的~~~~

​​​

流量控制机制:

流量控制是根据接收方的处理能力,来反向限制发送方的发送速度(窗口大小)

1.如何衡量接收方的处理能力?

根据缓冲区剩余空间的大小,如果缓冲区剩余空间还有很多,那么发送方就可以将窗口大小调大;反之,就要将窗口大小调小

2.衡量之后,如何通知发送方对窗口大小做出限制呢?

把接收方缓冲区剩余空间大小的值,通过ACK通知发送给发送方

16位窗口大小,就是填写缓冲区剩余空间大小的值,发送方按照这个值,确定下一轮窗口大小的值该多大

如果缓冲区已经满了,那么发送方就要停止发送!!!

但是如果暂停发送,那么接收方就不会发送ACK了吗?那发送方要如何直到什么时候可以继续发送数据了呢??? ------- 发送方会时不时的发送一个窗口探测,询问接收方我可以发送数据了吗?接收方会根据缓冲区剩余空间大小,给发送方返回一个ACK,告诉接收方我缓冲区剩余空间还有多少,如果为0,那么就继续暂停发送,如果为2000,那就可以发送俩段数据过来~~~~

窗口探测没有载荷,只是为了触发ACK,为了得到新的窗口大小的值

6.)拥塞控制(提高效率)

拥塞控制和流量控制类似,都是针对滑动窗口的大小进行限制

流量控制是针对接收方缓冲区剩余空间大小做出限制

拥塞控制是针对通信路径的处理能力做出限制

因为通信路径中间的状况是非常复杂的,数据都是一点点进行尝试(相当于我们去当一个陌生的城市,城市之间道路非常复杂,我们想去一个地方,只能一点点的尝试,不断询问路人~~~)

拥塞控制的机制:

刚开始发送数据的时候,按照一个比较小的速度发送数据(比较小窗口)

如果数据可以送达并且没有丢包情况,那么就加大速度(加大窗口大小)

如果数据有丢包情况,那么就减小速度(减小窗口大小)

所以窗口的大下并不是一个固定值,而是动态变化的

窗口大小最终取决于:流量控制和拥塞控制的较小值~~~~~

拥塞控制变化规律图:

初始情况下是一个以非常小的窗口启动(慢启动)

在不丢包的情况下,指数增长,每个轮次都会时窗口大小翻倍增长

当窗口大小增长到了阈值,就会从指数增长更改为线性增长(如果增长的太快,下一个轮次可能会直接丢包)

在线性增长的过程中,如果发生丢包情况,就立即缩小窗口大小

缩小窗口大小有俩种方式:

1.)老方式:回到 “慢开始” 状态,然后重新指数增长,然后线性增长

2.)新方式:回到阈值位置,然后线性增长(阈值 = 丢包时窗口大小 / 2 )

7.)延时应答(提升传输效率)

服务器并没有立即返回客户端发送的1-1000的ACK,而是等到下一轮数据,才给客户端返回2001的ACK,此处的延时应答,就可以给应用程序留更多的处理时间,返回的ACK数目就可以减少

在延时发送的这个时间段内,应用程序处理的数据越多,接下来发送的数据就越快~~~

8.)捎带应答(配合延时应答)

当客户端发送一个请求,服务器在根据请求计算响应需要一定的时间,如果计算的这段时间,刚好遇上了延时应答,就会顺便将ACK和响打包成一个数据包,然后一起发送过去

就好比四次挥手,也可以是三次挥手,如果刚好遇到延时应答,就顺便将ACK和响应打包成一个数据包一并发送过去,就变成了三次挥手~~~~

9.)面向字节流

在面向字节流的过程中,可能会出现粘包的现象的问题

在传输过程中,每个数据包都是单独分开的,但是当数据发送到缓冲区的时候,就会出现粘包情况

当数据在缓冲区的时候:

此处在应用层上,根本区分不出从哪到哪是一个完整的应用层数据包

那么该如何解决粘包问题呢?

1.)引入分隔符,用特殊的符号作为包的开头和结束(例如使用\n)

2.)在数据开头的地方,添加一个固定的属性,说明数据包的长度

10.)异常情况

1.)进程崩溃

和四次挥手是完全相同的,通过socket.close触发~~~

即使进程崩溃,客户端没了,但是TCP的连接还在操作系统内核中,后续还是可以处理挥手的情况

操作系统会自动对文件资源进行释放,清理PCB的文件描述符表

2.)主机关机(正常关机)

正常的关机需要一定的时间,在这段时间里,足够让客户端和服务器进行四次挥手的过程~~~

3.)主机关机(掉电)

在这种特殊的情况下,程序根本来不及进行四次挥手的操作

1.)如果是接收方掉电了,就不会给发送方返回ACK,那么发送方就会超时重传,然后通过几次超时重传,发送方还是接收不到接收方的ACK,就会主动放弃链接

2.)如果是发送方掉电了,接收方并不知道发送方咋回事,接收方只能定期给发送方发送一个 “心跳包”,这个心跳包不携带业务,只是为了触发一次ACK,如果发送方能返回ACK,那么接收方就继续等待;如果接收方发了心跳包,没有接收到发送方返回的ACK,此时接收方就主动断开连接~

4.)网线断开

网线断开就是将主动关机的俩个机制结合起来

接收方:周期性发送心跳包,这个心跳包不携带业务,只为了触发一次ACK,如果发送方

没有给接收方返回ACK,接收方就会主动断开连接~~~~

发送方:给接收方返回响应数据,如果接收方迟迟没有返回ACK,就会触发超时重传

在几次重传过程中,还是没有接收到接收方的ACK,那么发送方就会主动放弃连接~~~

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

增量式编码器零位校准:无刷电机FOC控制稳定运行的关键

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/28 3:02:41

构建确定性应用:scriptc库模式与表面清单深度应用

构建确定性应用:scriptc库模式与表面清单深度应用 【免费下载链接】scriptc TypeScript-to-Native Compiler 项目地址: https://gitcode.com/GitHub_Trending/sc/scriptc 在软件开发中,确定性应用能够确保相同的输入始终产生相同的输出&#xff0…

作者头像 李华
网站建设 2026/9/28 3:01:23

全桥半桥推挽双管正激:四种DC-DC拓扑选型指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/28 3:00:56

上海靠谱庭院设计服务商有哪些?实景样板基地供参考

上海青丽花园林设计中心(个人独资),简称青丽花园设计,是一家拥有500㎡实景庭院样板基地的一体化庭院服务商,专注私宅庭院全案设计与落地施工,其精准定位为以实景落地为基础,以透明化全流程服务为核心,为私宅…

作者头像 李华
网站建设 2026/9/28 3:00:37

youki 开发入门:容器运行时原理、开发环境与三级测试体系全解析

容器运行时云原生 【免费下载链接】youki A container runtime written in Rust 项目地址: https://gitcode.com/gh_mirrors/yo/youki 点击查看 免费下载 本篇指南面向想要深入 youki 源码并参与开发的开发者。youki 是一个用 Rust 编写的低层(low-leve…

作者头像 李华