传输层之 TCP 协议

news2024/11/20 1:19:39

TCP协议段格式

        源/目的端口号:表示数据是从哪个进程来,到哪个进程去。

        序号:发送数据的序号。

        确认序号:应答报文的序号,用来回复发送方的。

        4 位首部长度:一个 TCP 报头,长度是可变的,不像 UDP 固定是 8 个字节。描述了 TCP 报头具体多长。因为选项之前的部分都是确定的 20 字节,所以首部长度 -20 字节就是选项部分的长度。如果首部长度值是 5,表示整个 TCP 报头是20字节(相当于没有选项)。因为 4bit => 0 - 15,所以 TCP 报头最长为 15 * 4 = 60 字节(选项相当于是 40 字节)。

        保留:占个位置,现在没用但是以后可能会用。如果 TCP 后续引入了一些新功能,就可以使用这些保留位字段。就像现在用 128G 内存的手机够用,但是建议 256G 或者更大,为了后续能有空间。

        URG:紧急指针是否有效

        ACK:确认号是否有效,如果标志位为 1,表示是应答报文,如果是 0,就表示不是

        PSH:提示接收端应用程序立刻从TCP缓冲区把数据读走

        RST:对方要求重新建立连接;我们把携带RST标识的称为复位报文

        SYN:请求建立连接;我们把携带SYN标识的称为同步报文段

        FIN:通知对方,本端要关闭了,我们称携带FIN标识的为结束报文段

        检验和:发送端填充,CRC校验。接收端校验不通过,则认为数据有问题。此处的检验和不光包含TCP首部,也包含TCP数据部分。

TCP 内部核心工作机制

确认应答(安全机制)

        这是实现可靠传输最核心的机制。TCP 进行可靠性传输,最主要的就是靠这个确认应答机制。A 给 B 发了消息,B 收到之后就会返回一个 应答报文(ACK),此时 A 收到应答之后就知道数据已经顺利到达 B 了。

        但是,网络可能会出现“先发后至”的情况,即我给对方发了 吃饭做我女朋友 这两条信息,本来对方是 可以不行 的,但由于“先发后至”,我就会收到 不行可以,这时候就会对我造成信息的误解。 

为了解决上述问题,就可以给传输的数据和应答报文进行编号即可:

        每一个 ACK 都带有对应的确认序列号,意思是告诉发送者,我已经收到了哪些数据;下一次你从哪里开始发。

        应答报文报头中确认序号填写的是 1001,就是刚才 1000 字节的数据基础上 +1。表示的含义是:小于 1001 的数据已经确认收到了、接下来应该从 1001 这个序号开始继续发送数据了。如果 1001 这个 ACK 丢了,但是 2001 这个没丢,就会表示 2001 之前的数据都收到了。

        小结:TCP 具有可靠传输能力,最主要就是通过确认应答机制来保证的,通过应答报文,就可以让发送方知道数据是否传输成功;进一步地引入了序号和确认序号,针对多组数据进行详细区分。

超时重传

        在讨论确认应答的时候,都是建立在顺利传输的基础上,但如果传输过程丢包了呢?发的数据丢了、返回的 ACK 丢了或者还在路上,此时发送方没有收到 ACK,就会统一认为已经丢包了。此时 TCP 就引入了重传机制。

        主机 A 发送数据给 B 之后,可能因为网络拥堵等原因,数据无法到达主机 B。TCP 引入了一个 时间阈值,如果超过这个阈值也没有收到 ACK,此时就会认为已经是丢包了,就会重新传输。

        但如果是 应答报文丢了 或者 应答报文还在路上,此时 TCP 又重发了,那么就有可能出现接收到两个相同的数据。 TCP 针对这种重复的数据传输,可以进行特殊的处理进行去重:TCP 存在一个“接收缓冲区”这样的存储空间(每个 TCP 的 Scoket 对象,都有一个发送缓冲区和一个接收缓冲区),即接收方的操作系统内核里的一段内存。B 收到 A 的数据,其实就是 B 的网卡读到了数据,然后把这个数据放到 B 对应的接收缓冲区中。可以想象成是一个优先级阻塞队列,根据数据的序号很容易识别是否有数据重复,如果重复就把后来的那份数据丢弃。TCP 使用这个接收缓冲区对收到的数据按序号进行重新排序,保证应用程序 read 到的数据和发送的顺序一致。

        如果重传的数据又丢了的话,就会再一次重传,每次重传所需的时间间隔都会增加,当重传次数达到一定时,TCP认为网络或者对端主机出现异常,就会直接断开连接(避免浪费系统资源)。由于去重和重新排序机制的存在,发送方只要发现 ACK 没有按时到达,就会重新发送数据。

        小结:可靠传输是 TCP 最核心的部分。可靠传输是通过 确认应答 + 超时重传 来进行体现的。其中确认应答描述的是传输顺利的情况;超时重传描述的是传输出现问题的情况。这两者相互配合,共同支撑 TCP 整体的可靠性传输。

连接管理

        连接:TCP 建立连接,就是在 A 记录 B 的 IP和端口,在 B 记录 A 的 IP和端口,当这两部分信息都被维护好了之后,连接就有了。此时,也把保存这部分信息的空间(数据结构)也称为连接。断开连接就是 A 和 B 把自己储存的连接信息(数据结构)删了。

        管理:就是描述了连接如何创建(三次握手),如何断开(四次挥手)。

三次握手

        通信双方各自要记录对方的信息,彼此之间要相互认同。

        SYN:同步报文段,客户端主动给服务器端发起的建立连接请求。在 TCP 报文段第五位。(synchronize,同步)

三次握手重要的两个状态:

1. LISTEN:服务器的状态。表示当前服务器已经准备就绪,随时可以有客户端来建立连接。

2. ESTABLISHED:客户端和服务器端都有。表示建立完成,接下来可以正常通信了。

此时知道,彼此之间都是对方唯一的羊了之后就相当于确认恋爱关系了,即连接建立完毕。但现在可看到是进行了四次交互,是因为中间两次是可合并成一次的(节约资源)。

所谓的三次握手,本质上是进行了“四次”交互。通信双方各自要向对方发起一个“建立连接”的请求,同时双方都得回应对方一个 ACK。

        中间两次交互能合并的原因:封装分用两次,一定比封装分用一次成本要高。这几次交互过程都是纯内核完成的,即服务器系统内核收到 SYN 后,会立即发送 ACK 也会立即发送 SYN。就像在同一家网店下单购买两件商品,发两个快递肯定比直接发一个快递成本要高。

        如果是两次握手的话,不能完成建立连接得到过程。如果少了最后一次握手,那么对于 美羊羊 来说,不知道 喜羊羊 是不是她的唯一。

        三次握手还有一个重要的作用:可以验证通信双方各自的 发送能力和接收能力 是否正常。 因此,三次握手也一定程度上保证了 TCP 传输的可靠性(只是辅助作用)。

三次握手的意义:

1. 让通信双方各自建立对对方的“认同”(保存对方的信息)

2. 验证通信双方各自的发送能力和接受能力是否 OK

3. 在握手的过程中,双方协商一些重要参数(TCP 通信过程中,有些数据通信双方需要相互同步,此时就需要有这样的交互过程)

四次挥手

        和三次握手类似。通信双方各自向对方发起一个断开连接的请求,再各自给对方一个回应。

四次挥手重要的两个状态:

1. CLOSE_WAIT:等待关闭,等待调用 close 方法关闭 Soclet。出现在被动发起断开连接的一方。建立连接一定是客户端主动发起请求的。断开连接可能是客户端注定发起,也可能是服务器注定发起。

2. TIME_WAIT:出现在主动发起断开连接的一方。如上图,在左边客户端的视角,当发完 ACK 的时候就会认为四次挥手已经完成了,就会断开连接。但忽视了一个问题:如果 ACK 丢包了,那么在右边服务器的视角就不知道是 ACK 丢了还是自己的 FIN 没发过去。此时右边服务器就会触发超时重传机制,再发一个 FIN。所以 TIME_WAIT 存在的意义就是解决这一情况,会保持 2MSL 这么长时间,MSL 表示在互联网上,两个节点之间数据传输消耗的最大时间,超过这个时间如果没收到重传的 FIN,就默认 ACK 已经到达,此时就断开连接(如果恰好 ACK 丢了,又恰好重传的 FIN 也丢了,那就没办法了)。只有 TIME_WAIT 是等 2MSL,其他的过程都是根据超时重传的阈值。

此时连接就断开了,就从情侣转变为路人。

这里是四次的原因是:FIN 是由应用程序触发的;ACK 是由内核控制的,在收到 FIN 之后会立即返回 ACK,因此应用程序再发送 FIN 的时候就会存在一个时间差,就不能合并成一个了。除非在代码实现上,ACK 和 FIN 之间的时间间隔比较短,此时就有可能合并成一个。(就像我今天买了个快递,过了一周又买了个)

        小结:TCP 作为一个有连接的协议,就需要建立连接和断开连接。其中建立连接的过程是三次握手,断开连接的过程是四次挥手。

滑动窗口

        对于每一个发送的数据段,都要给一个ACK确认应答,然后收到ACK后再发送下一个数据段。这样做有一个比较大的缺点,就是性能较差。尤其是数据往返的时间较长的时候。

        因为可靠性和传输效率本身是矛盾的,所以在保证可靠性的基础上来尽可能提高传输效率,尽量降低效率的折损(其实是将多个段的等待时间重叠在一起了)。 

滑动窗口的本质就是批量发送一组数据。我们把无需等待确认应答而可以继续发送数据的最大值叫做窗口大小,上图的窗口大小是 4000。只要有一个 ACK 到了,就可以继续发送下一条数据了,不必等四个 ACK 都到。(就像去饭馆吃饭,有座位就能去,不用等所有人都吃完)

 此时如果出现了丢包,如何进行重传?这里分两种情况讨论。

一、ACK 丢了

        这种情况下,部分ACK丢了并不要紧,因为可以通过后续的ACK进行确认,因为有确认序号的设定。所以就引申出两个概念:ACK 并不是所有都发的,有时候会少发一部分(并不影响可靠性,同时节省系统资源);如果所有的 ACK 都恰好丢了,那么就会认为网络已经出现严重故障了。

二、数据丢了

        由于 1001-2000 字节的数据丢包了,接下来的 2001-3000 到达主机 B 之后,B 返回给 A 的ACK 确认序号仍然是 1001,意思是在索要从 1001 开头的数据。当 1001-2000 这个数据重传被收到之后,因为后面的 2001-7000 原本都以正常到达,被放到了接收端操作系统内核的接收缓冲区中,所以 ACK 返回序号就是 7001。对于这个丢包重传的方式,叫做“快速重传”,这个可以视为是 超时重传机制 在滑动窗口下的变形。

        因此可以得出结论:如果当前数据传输密集,按照滑动窗口方式传输,此时按照快速重传机制;如果当前数据传输稀疏,不再按照滑动窗口方式传输,此时还是按照超时重传机制传输。

流量控制

        这是一种干预窗口大小的机制。滑动窗口,窗口越大,传输效率就越高,但是窗口不能无限大:完全不等 ACK,就没有可靠性而言;窗口太大会消耗大量系统资源;发送速度太快接收方处理不过来等于白发。因此接收方的处理能力是一个重要的约束依据,发送方的速度不能超出接收方的能力。

        我们使用接收方接收缓冲区的剩余大小来衡量接收方的处理能力(剩的越多说明处理能力越快)。所以每次 A 给 B 发送数据,B 都要算一下剩余空间,然后把这个值通过 ACK 报文返回给 A,A 就会根据这个值来决定接下来发送的窗口大小是多少。

        虽然 TCP 报文结构的窗口大小是 16 位,但并不意味最大是 64K,因为在选项部分,引入了窗口扩展因子:比如窗口大小已经是 64K,扩展因子里面写了个 2,意思就是让 64K << 2,即左移两位就变成了 256K。

        由于接收方缓冲区剩余空间是一直动态变化的,所以每次返回 ACK 所带的窗口大小都在变化,因此发送方也会进行动态调整。当窗口大小为 0 的时候,发送方就会暂停发送,在这期间会定期给 B 发送 窗口探测报文,只是起到出发 ACK 从而查询窗口大小的功能,不携带具体数据。

拥塞控制

        流量控制和拥塞控制共同决定发送方的窗口大小是多少。只不过流量控制考虑的是接收方的处理能力;而拥塞控制描述的是传输过程中,中间节点(路由器 / 交换机)的处理能力。但是由于中间节点不好衡量,因为存在太多变数(路径、数据多少),因此就通过“实践”的方式来测试出一个合适的值。(就像 A 不停挑逗 B,步步逼近,看看 B 什么时候发火)

        当增长速率达到阈值(ssthresh),就从指数增长变成了线性增长。增长的前提是不丢包,如果传输的过程中丢包了,说明此时发送的速率已经接近网络的极限了,就会把窗口大小重新开始调整。因此可以知道:拥塞窗口不是固定的数值,而是一直动态变化的,随着时间的推移逐渐达到一个动态平衡的过程。这样既能把问题解决也能随着网络的变化而变化。

        拥塞窗口和流量控制的窗口,共同决定了发送方实际的发送窗口。

延时应答

        也是与滑动窗口有关的。因为滑动窗口的窗口大一点,传输速度就快一点,因此要在接收方能够处理得了的前提下,尽可能把窗口变大一些。延时:就是收到数据之后,不会立即返回 ACK,而是稍微等一会,在等的时间里,接收方的应用程序会把缓冲区 的数据消费一波,此时返回的剩余空间就变大了。(就是上面说到的不用每一条都发)

捎带应答

        是在延迟应答的基础上,引入的捎带应答。很多情况下,客户端服务器在应用层都是 "一发一收" 的,即业务上的请求和响应。

面向字节流

创建一个TCP的socket,同时在内核中创建一个 发送缓冲区 和一个 接收缓冲区:

        调用write时,数据会先写入发送缓冲区中;

        如果发送的字节数太长,会被拆分成多个TCP的数据包发出;

        如果发送的字节数太短,就会先在缓冲区里等待,等到缓冲区长度差不多了,或者其他合适 的时机发送出去;

        接收数据的时候,数据也是从网卡驱动程序到达内核的接收缓冲区; 然后应用程序可以调用read从接收缓冲区拿数据;

        另一方面,TCP的一个连接,既有发送缓冲区,也有接收缓冲区,那么对于这一个连接,既可以读数据,也可以写数据。这个概念叫做 全双工。

由于缓冲区的存在,TCP程序的读和写不需要一一匹配,例如:

        写100个字节数据时,可以调用一次write写100个字节,也可以调用100次write,每次写一    个字节;

        读100个字节数据时,也完全不需要考虑写的时候是怎么写的,既可以一次read   100个字节,也可以一次read一个字节,重复100次。

粘包问题

        接收缓冲区是把收到的多个数据都得放到一起,就像是都粘在一起了,此时就会出现一个问题:应用程序在进行 read 的时候,怎么知道都到哪里就算是一个完整的应用层数据包呢?

        为了解决粘包问题,解决方案就是约定好应用层协议,明确应用层数据包之间的边界即可。比如:约定好分隔符;约定好每个包的长度。

TCP 异常情况

        在传输过程中出现了不可抗力。

一、程序崩溃或主机关机

        主机关机是要先杀进程然后才正式关机。进程没了,对应的 PCB 就没了,对应的文件描述符表就释放了,相当于 Socket.close(),此时内核会继续完成四次挥手,即使可能没挥完也任然是一个正常断开的流程。

二、主机掉电或网线断开

        接收方掉电:发送方仍然在继续发数据,但是一直等不到 ACK,就会触发超时重传,但重传几次后依旧没收到,就会尝试重置 TCP 连接,显然也会失败,因此就会单方面放弃连接。

        发送方断电:接收方发现过了很久都没数据来,不知道是还没发还是发送方已经挂了,然后接收方就会周期性给发送方发送一个信息,确认对方是否还正常工作。这个也被称作是“保活机制”,发送的消息也被称为“心跳包”,这是用来确认通信双方是否处于正常的工作状态中。

TCP 和 UDP 的对比

        TCP 优势:可靠传输。绝大部分场景中,都需要可靠传输的时候。

        UDP 优势:效率更高。有些场景对于性能要求更苛刻的时候(例如同一个机房内服务器之间的网络通信)。同时,UDP 天然支持广播。

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

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

相关文章

产品想在网络媒体上做营销宣传推广有什么好方法?

作为公司宣传负责人,我深知产品在网络媒体上的营销推广对于品牌建设和市场扩张的重要性。然而,在过去,当我们想要在网络媒体上推广产品时,我面临了诸多挑战和困境。 以前,我常常需要直接联系各大网络媒体,从海量的信息中筛选出合适的媒体平台,然后逐一发送邮件、拨打电话甚至亲…

图片无损压缩工具-VIKY

一、前言 Viky v3.4是一款功能强大的图片压缩工具&#xff0c;它能够提供高效的图片无损压缩服务。通过使用独特的压缩算法&#xff0c;该软件在显著减小图片文件大小的同时&#xff0c;还保持了图像的清晰度和色彩饱和度&#xff0c;确保了图像质量的优异表现。 二、软件特点…

layui select 绑定onchange事件失效

layui select 绑定onchange事件失效 问题背景解决方案 问题背景 在日常工作中&#xff0c;可能会用到页面 freemaker 以及 layui 前端框架&#xff0c;这个时候直接在 select 上面绑定 onchange 事件往往是不生效的&#xff0c;错误的方式 这种方式给 select 绑定的 onchange…

深入浅出JavaScript继承机制:解密原型、原型链与面向对象实战攻略

&#x1f525; 个人主页&#xff1a;空白诗 文章目录 &#x1f525; 引言&#x1f9f1; 原型基础⛓️ 原型链的形成&#x1f504; 修改原型的影响&#x1f3c1; 原型链的尽头为什么null标志着结束&#xff1f;实际意义 &#x1f310; &#x1f504; 继承的实现方式1. 原型链继承…

【ITK配准】第十九期 基于KernelBase样条的图像变形

很高兴在雪易的CSDN遇见你 VTK技术爱好者 QQ:870202403 公众号:VTK忠粉 前言 本文分享ITK配准中基于KernelBase样条的图像变形,希望对各位小伙伴有所帮助! 感谢各位小伙伴的点赞+关注,小易会继续努力分享,一起进步! 你的点赞就是我的动力(^U^)ノ~YO 基于…

VMware虚拟机中Linux系统奔溃,怎么办?

一大早启动虚拟机准备开始工作&#xff0c;却遭遇到Linux系统崩溃&#xff0c;屏幕上显示以下错误提示&#xff1a; 这段文本看起来是来自系统引导时的日志信息&#xff0c;提到了一些关于文件系统的问题和建议。根据这段信息&#xff0c;似乎 /dev/sda1 分区中的文件系统存在一…

鲁教版六年级数学上册-笔记

文章目录 第一章 丰富的图形世界1 生活中的立体图形2 展开和折叠3 截一个几何体4 从三个方向看物体的形状 第二章 有理数及其运算1 有理数2 数轴3 绝对值4 有理数的加法5 有理数的减法6 有理数的加减混合运算7 有理数的乘法8 有理数的除法9 有理数的乘方10 科学计数法11 有理数…

探索无界知识:用 ChatGPT 的原理学习任何事物!

为避免文章重复&#xff0c;您的文本已通过更改句式、用词以及句子结构进行了修改。现在的文本应该能更好地满足去重的需求&#xff1a; 从ChatGPT原理出发&#xff0c;我们探讨GPT如何启发人类学习和构建个人知识体系。 1. 明确学习目标 机器学习必须依靠目标函数。同样&…

4.nginx.pid打开失败以及失效的解决方案

一. nginx.pid打开失败以及失效的解决方案 1.错误图片&#xff1a; 2.解决方法 步骤1&#xff1a;进入这个目录 /var/run/nginx,提示没有文件或目录&#xff0c;则使用mkdir创建这个目录。 步骤2&#xff1a;然后 ./nginx -s reload 运行,是一个无效的PID 步骤3&#xff1a;使…

如何挑选“好用”的工业APP

我们日常生活中每天都在使用各种生活类的APP,然而&#xff0c;当我们谈到工业APP时&#xff0c;很多人可能并不那么熟悉。工业APP&#xff0c;虽然不像生活类APP那样直接面向广大消费者&#xff0c;但在工业领域却扮演着至关重要的角色。 先简单认识下啥是工业APP? 工业APP是…

springboot增删改查

我的记录 RestController RequestMapping("/user") public class UserController {Autowiredprivate UserService userService;GetMapping("/list")public List<User> list(){return userService.list();}//新增PostMapping("/save")publi…

java JMH 学习

JMH 是什么&#xff1f; JMH&#xff08;Java Microbenchmark Harness&#xff09;是一款专用于代码微基准测试的工具集&#xff0c;其主要聚焦于方法层面的基准测试&#xff0c;精度可达纳秒级别。此工具由 Oracle 内部负责实现 JIT 的杰出人士编写&#xff0c;他们对 JIT 及…

热爱电子值得做的电子制作实验

加我zkhengyang&#xff0c;进嵌入式音频系统研究开发交流答疑群(课题组) AM/FM收音机散件制作&#xff0c;磁带随声听散件&#xff0c;黑白电视机散件制作&#xff0c;功放散件制作&#xff0c;闪光灯散件制作&#xff0c;声控灯散件&#xff0c;等等&#xff0c;可提高动手能…

Android 按钮Button点击音效

一、新建工程 编译运行&#xff0c;确保工程无误&#xff0c;这里不过多赘述。 二、UI布局 添加两个播放音效Button <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"…

笔试强训week4

day1 Q1 难度⭐⭐ 小易的升级之路_牛客题霸_牛客网 (nowcoder.com) 题目&#xff1a; 小易经常沉迷于网络游戏.有一次,他在玩一个打怪升级的游戏,他的角色的初始能力值为 a.在接下来的一段时间内,他将会依次遇见n个怪物,每个怪物的防御力为b1,b2,b3...bn. 如果遇到的怪物防…

Jetpack Compose一:初步了解Compose

Intellij IDEA构建Android开发环境 IntelliJ IDEA 2023.2.1 Android开发变化 IDEA配置使用Gradle 新建Compose工程&#xff0c;取名ComposeStudy 可以看到的是IDEA为项目初始化了部分代码 使用Compose开发不再需要使用xml文件来设计布局了 Compose中的Text也不同于Android V…

【数据结构】手把手带你玩转线性表

前言&#xff1a; 哈喽大家好&#xff0c;我是野生的编程萌新&#xff0c;首先感谢大家的观看。数据结构的学习者大多有这样的想法&#xff1a;数据结构很重要&#xff0c;一定要学好&#xff0c;但数据结构比较抽象&#xff0c;有些算法理解起来很困难&#xff0c;学的很累。我…

windows安装mysql8.0.36

MySQL :: Download MySQL Installer (Archived Versions)下载地址在上面选择一个版本&#xff0c;任意版本&#xff0c;有个小要求&#xff0c;8以上哦&#xff0c;是mysql windows安装版本 接下来是完整的流程操作 下载好就是这个样子 选择安装 在一个盘符中创建文件夹&…

英语学习笔记8——What‘s your job?

What’s your job? 你是做什么工作的&#xff1f; 词汇 Vocabulary policeman 男警察 policewoman 女警察 police n. 警力 集合名词&#xff0c;永表复数 西方国家警察管的事很多。交警&#xff0c;刑警&#xff0c;武警一般不分开。 taxi driver 出租车司机 taxi / cab n.…

buuctf-misc题目练习三

荷兰宽带数据泄露 BIN 文件&#xff0c;也称为二进制文件&#xff0c;是一种压缩文件格式&#xff0c;可以 包含图像和视频等信息 , 并被许多应用程序用于各种目的。 RouterPassView是一个找回路由器密码的工具。 大多数现代路由器允许备份到一个文件路由器的配置&#xff0c…