JavaEE 初阶篇-深入了解网络原理 TCP/IP 协议

🔥博客主页: 【小扳_-CSDN博客】
❤感谢大家点赞👍收藏⭐评论✍

文章目录

        1.0 TCP 协议概述

        1.1 TCP 协议格式

        2.0 TCP 协议的特性

        2.1 确认应答

        2.2 超时重传

        2.2.1 超时的时间如何确定?

        2.3 连接管理

        2.3.1 三次握手

        2.3.2 四次挥手

        2.3.3 为什么是 TIME_WAIT 的时间是 2 MSL ?

        2.3.4 服务器出现大量的 CLOSE_WAIT 是什么导致的?

        2.4 滑动窗口

        2.4.1 遇到丢包情况该 TCP 该如何进行重传?

        2.5 流量控制

        2.6 拥塞控制

        2.7 延迟应答

        2.7.1 所有的包都可以延迟应答吗?

        2.8 捎带应答

        2.9 粘包问题

        2.9.1 如何避免粘包问题呢?

        2.9.2 UDP 会存在粘包问题吗?

        2.10 异常情况


        1.0 TCP 协议概述

        TCP 协议在传输层,TCP 是传输层协议的一种,传输层中的协议不单单只有 TCP 或者 UDP 。当应用层将数据打包后交给传输层时,如果选择使用 TCP 协议,传输层会在数据包上加上 TCP 报头;如果选择使用 UDP 协议,传输层会在数据包上加上 UDP 报头。

        1.1 TCP 协议格式

        1)源端口号:表示数据从哪个应用程序发送出来。

        2)目的端口号:表示数据要发送到哪个目的应用程序中。

        3)32 位序号:TCP 协议中的序号是记录字节流中第一个字节的编号。每个 TCP 报文段都有一个序号字段,用来标识该报文段中第一个字节在整个字节流中的位置。接收端根据序号对接收到的数据进行排序和重组,确保数据的有序传输和可靠性。

        简单来说,发送方会对发送的每一个字节进行排序编号,一个字节一个编号。比如,发送从编号为 1 到编号为 1000 的字节,那么此时的 TCP 报头序号中就会记录编号 1 。

        4)32 位确认序号:当接收方接收到了 TCP 的数据包,那么就会响应一个确认序号。比如,发送方:发送从编号为 1 到编号为 1000 的字节。接收方接收:该数据包之后,会给发送方一个响应 1001 ,所以该响应的序号就是确认序号。

        总结一下,确认序号是指下一个期望接收的字节序号,用来告知发送方接收方已经成功接收到的数据包的序号。

        5)4 位头部长度:又称为 4位 TCP 报头长度,表示该 TCP 头部有多少个 32 位 bit (有多少个 4 字节),所以 TCP 头部最大长度是 15 * 4 = 60 个字节长度。

        6)6 位保留:保留的是头部长度,所以以后 TCP 所需要的报头不够时,那么就可以从保留的空间中给报头长度进行扩展,不过保留的最大只有 6 个 bit 。

        7)6 位标志位

        URG:紧急指针是否有效。

        ACK:确认号是否有效,当接收方接收到数据时,就会发送 ACK 信号进行响应。

        PSH:提示接收端应用程序立刻从 TCP 缓冲区把数据读走,接收方中会有一个容器进行存储数据,该容器相当于是一个优先级阻塞队列(缓冲区)。

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

        SYN:请求建立连接。

        FIN:请求断开连接。

        8)16 位窗口大小:发送方根据接收方返回的窗口大小来控制发送数据的速度,以避免发送过多数据导致网络拥塞。如果接收方的窗口大小为0,发送方将停止发送数据,直到接收方的窗口大小变为大于0为止。可以实现流量控制和拥塞控制,从而保证数据传输的可靠性和效率。

        9)16 位校验和:发送方填充,CRC 校验,接收方进行校验,若校验不通过,则认为数据有问题。此处校验和不光包含 TCP 首部,也包含 TCP 数据部分。

        10)16 位紧急指针:标识哪部分是紧急数据。

        2.0 TCP 协议的特性

        TCP 重要的特性:确认应答、超时重传、连接管理、滑动窗口、流量控制、拥塞控制、延迟应答、捎带应答、粘包、异常情况等特性来确保 TCP 可靠性和高的性能。

        2.1 确认应答

        接收方在接收到数据包后会发送确认应答给发送方,确保发送方知道数据包已经成功到达。通过 TCP 报头中的序号和确认序号来实现该机制,当发送方发送的字节,报头中会记录第一个字节的序号,当接收方接收到该数据时,会给发送方响应一个确认序号。表示:接收方已经接收到了数据了,期待下一个数据,下一个数据从第几个字节开始。

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

如图:

        2.2 超时重传

        当主机 A 发送数据,一段时间后,没有接收到主机 B 的响应,就会触发超时重传。

        分两种情况:

        1)主机 A 发送的数据,因为某个原因导致在中间丢包了,那么这种情况,确实要通过超时重传:主机 A 重新发送数据到主机 B 中。这种情况没有太大问题。

        2)主机 A 发送的数据,主机 B 接收到了,当主机 B 发送 ACK 进行响应,那么 ACK 因某个原因导致丢包了,那么主机 A 过一段时间,没有接收到响应,就会触发超时重传,这可能就会有问题了,本来主机 B 已经接收到了数据,主机 A 触发了超时重传,又继续给主机 B 发送相同的数据。

        因此主机 B 会收到很多重复数据,那么 TCP 协议需要能够识别出哪些包是重复的包,并且把重复的丢弃掉,这时候我们可以利用前面提到的序列号,就可以很容易做到去重的效果。

        2.2.1 超时的时间如何确定?

        最理想的情况下,找到一个最小的时间,保证“确认应答一定能在这个时间内返回”,但是这个时间的长短,随着网络环境的不同,是有差异的。

        如果超时时间太长,会影响整体的重传效率;

        如果超时时间太短,有可能会频繁发送重复的包;

        因此 TCP 为了保证无论在任何环境下都能比较高性能的通信,会动态计算这个最大超时时间。累计到一定的重传次数, TCP 认为网络或者对端主机出现异常,强制关闭连接。

        2.3 连接管理

        正常情况下:TCP 通过三次握手建立连接、通过四次挥手断开连接。

        2.3.1 三次握手

        具体流程:

        主机 A 要想跟主机 B 建立连接,首先主机 A 会发送带有 SYN 信号的 TCP 给到主机 B ,来请求建立连接。seq 是序列号,发送的数据的第一个字节序号为 x 。当主机 A 发送完请求连接时,处于 SYNSENT 状态,该状态表示:等待响应。

        此时主机 B 正在出于监听状态,监听来自客户端的连接请求。所以 LISTEN 状态通常是服务器在等待客户端连接时的初始状态。

        当主机 B 接收到主机 A 发送的请求连接信息时,主机 B 会响应带有 ACK 信号的 TCP ,代表已经接收到数据了,确认学号 ack 为 x + 1,表示期待接收下一个数据为:x + 1,同时还带有 SYN ,表示主机 B 请求与主机  A 建立连接。当主机 B 发送完 SYN ,处于 SYNRCVD 状态,该状态表示:服务器已经接收到客户端发送的 SYN 包,并已经发送了自己的 SYN 包作为响应,表示同意建立连接。

        当主机 A 接收到了主机 B 发送的 TCP 包时,会发送一个带有 ACK 信号的 TCP,表示:已经接收到数据了,seq 序列号:记录发送数据中的第一个字节序号为 x + 1。

        最后,双方就成功建立了连接,都处于 ESTABLISHED 状态。在 ESTABLISHED 状态下,双方可以互相发送数据,进行通信和交换信息。

建立连接的意义:

        1)投石问路,确认当前通信路径是否通畅。

        2)确保双方都具备接收数据的能力。

        3)协商参数,通信双方共同确认一些通信中的必备参数数值,比如协商序列号。

        2.3.2 四次挥手

        具体流程:

        客户端想要断开与服务器的连接,首先,客户端会发送带有 FIN 信号的 TCP 包给服务器。

        服务器先会响应带有 ACK 信号的 TCP 包给客户端,表示:服务器已经接收到数据了。此时服务器可能还没有接收完数据,需要继续接收数据,还不能断开连接。服务端此时处于 CLOSEWAIT 状态。等待数据接收完毕了,手动调用 close() 方法,服务端会主动发送带有 FIN 信号的 TCP 给客户端。

        最后客户端接收到服务端发送的 TCP 包后,就代表着可以正式断开连接了,因此客户端发送带有 ACK 信号的 TCP ,服务端此时处于 LASTACK 状态,接收最后一个 ACK 信号。当服务端接收完毕之后,就会处于 CLOSE 状态,服务端就成功断开连接了。

        对于客户端来说还需要等待 2MSL ,而不是立马像服务端直接结束。这是因为,万一客户端发送的 ACK 在中间丢包了,就需要触发超时重传,所以需要等待一段时间,来确保 ACK 成功发送到服务器中。

        2.3.3 为什么是 TIME_WAIT 的时间是 2 MSL ?

        1)MSL 是 TCP 报文的最大生存时间,因此 TIME_WAIT 持续存在 2 MSL 的话,就能保证在两个传输方向上的尚未接收或者迟到的报文都已经消息。 

        2)也是理论上保证最后一个报文可靠到达(假设最后一个 ACK 丢失,那么服务器会再重发一个 FIN ,这时虽然客户端的进程不在了,但是 TCP 连接还在,仍然可以重发 LAST_ACK)

        2.3.4 服务器出现大量的 CLOSE_WAIT 是什么导致的?

        一般而言,对于服务器上出现大量的 CLOSE_WAIT 状态,原因就是服务器没有正确的关闭 socket.close() ,导致四次挥手没有正确完成,这是一个 BUG ,只需要加上 close 即可解决问题。 

        2.4 滑动窗口

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

        对于这种情况,就引入了滑动窗口。TCP 报头上的窗口大小值的是,无需等待确认应答而可以继续发送数据的最大值。

举个例子:

        窗口大小为 4 ,发送前四个数据的时候,不需要等待任何 ACK ,直接发送;收到第一个 ACK 后,滑动窗口向后移动,继续发送第五个数据;依此类推;

        这样就有效提高效率了,当发送数据的时候,同时也等待着下一个 ACK 。当速度够快时,看起来就像一下子移动 4 格。

        操作系统内核为了维护这个滑动窗口,需要开辟发送缓冲区来记录还有哪些数据没有应答;只有确认应答过的数据,才能从缓冲区删掉。

        窗口越大,则网络的吞吐率就越高。

        2.4.1 遇到丢包情况该 TCP 该如何进行重传?

        这里分两种情况进行讨论。

        1)数据包已经抵达,只是 ACK 被丢失了。

        这种情况下,部分 ACK 丢了并不要紧,因为可以通过后序的 ACK 进行确认。因为只要后序的 ACK 返回了,就代表着前面的数据包都接收完毕了,只是 ACK 丢了仅此而已。

        2)出现数据包丢了的情况。

        当某一段数据丢失之后,发送端会一直收到 1001 这样的 ACK ,就像在提醒发送端“我想要的是 1001 一样”;

        如果发送端主机连续三次接收到 1001 这样的应答,那么发送端就会在缓冲区中拿到相应的数据重新发送。

        这个时候接收端收到 1001 之后,再次返回的 ACK 就是 7001 了,接收端其实之前就已经接收到,被放到接收缓冲区中;这种机制被称为“高速重发控制”(也叫“快重发”)。

        2.5 流量控制

        接收端处理数据的速度是有限的,如果发送端发的太快,导致接收端的缓冲区被打满,这时候如果发送端继续发送,就会造成丢包,继而引起丢包重传等等一系列连锁反应。

        因此 TCP 支持根据接收端的处理能力,来决定发送端的发送速度,这个机制就叫做流量控制。

        接收端将自己可以接收的缓冲区大小放入 TCP 首部中的“窗口大小”字段,通过 ACK 端通知发送端。窗口大小字段越大,说明网络的吞吐量越高。接收端一旦发现自己的缓冲区快满了,将会将窗口大小设置成一个更小的值通知给发送端。发送端接收到这个窗口之后,就会减慢自己的发送速度。如果接收端缓冲区满了,就会将窗口置为 0,这时发送方不再发送数据,但是需要定期发送一个窗口探测数据段,使接收端把窗口大小告诉发送端。

        2.6 拥塞控制

        TCP 引入慢启动机制,先发送少量的数据,探探路,摸清当前的网络拥堵状态,再决定按照多大的速度传输数据。

        一开始的时候会慢启动,窗口大小一般从 1 开始往上增加,这是因为刚开始发送数据时,不清楚具体的网络环境状况,则窗口需要根据实际的网络情况来增加。一开始,发送方每接收到一个 ACK ,窗口就会 +1 ,指数式增长,到一定的阈值之后,按照线形方式增长。

        1)TCP Reno 版本

        一开始的阈值为 16 ,超过这个数值,就会以线性方式继续增长,当收到 3 个重复 ACK 执行快重传时,说明此时网络拥塞,那么就需要将窗口大小就会恢复到拥塞的一半 12 。继续以线性的方法继续增长。依次类推,最后会达到一个稳定的窗口大小情况。

        2)TCP Tahoe 版本

        当接收到多个快重传时,首先窗口会重新从 1 开始往上增加,没接收到一个 ACK 就会窗口大小 +1 ,且阈值变成拥塞时窗口大小的一半。当窗口大小增加到 12 前,以指数方式增长,一旦超过 12 ,以线性方法继续增长,以此类推。

        每次发送数据包的时候,将拥塞窗口和接收端主机反馈的窗口大小做比较,取较小的值作为实际发送的窗口。

        2.7 延迟应答

        在TCP通信中,接收端收到数据后会发送确认应答,确认已经接收到数据。如果接收端立即发送确认应答,那么发送端会根据确认应答的窗口大小来继续发送数据。如果确认应答的窗口大小比较小,发送端发送的数据量就会受限,影响了传输效率。

        而如果接收端延迟发送确认应答,等待一段时间后再发送,那么确认应答的窗口大小可能会更大。这样一来,发送端可以发送更多的数据,提高了网络传输效率。因为窗口越大,发送端就可以发送更多的数据,从而提高了网络吞吐量。

        发送窗口大小受到接收方的缓冲区剩余大小和延迟应答策略的双重影响。接收方的缓冲区大小决定了最大的发送窗口大小,而延迟应答可以在这个范围内动态调整确认应答的窗口大小。

        2.7.1 所有的包都可以延迟应答吗?

        肯定不是。

        1)数量限制:每隔 N 个包就应答一次。一般 N 取 2 。

        2)时间限制:超过最大延迟时间就应答一次。超时间取 200 ms 。

        2.8 捎带应答

        捎带应答是指在发送 TCP 报文时,如果接收方正好有数据要发送给发送方,那么可以将这些数据捎带在 TCP 报文的 ACK(确认)中一起发送,而不需要额外发送一个单独的数据包。

        这种捎带应答的机制可以提高网络的利用率和效率,减少网络传输时延。当接收方收到数据后,如果刚好有数据要发送给发送方,可以直接在 ACK 中回复,并携带需要发送的数据,这样可以减少网络传输的次数,提高网络的吞吐量。

        需要注意的是,捎带应答只能在 TCP 中使用,而且只能在接收方发送 ACK 时才能进行,发送方不能在发送数据时捎带应答。

        2.9 粘包问题

        首先明确,粘包问题中的“包”,是指的应用层的数据包。在 TCP 的协议头中,没有如同 UDP 一样的“报文长度”这样的字段,但是有一个序号这样的字段。

        站在传输层的角度,TCP 是一个一个报文过来的,按照序号排好放在缓冲区中。

        站在应用层的角度,看到的只是一串连续的字节数据。

        那么应用程序看到了这么一连串的字节数据,就不知道从哪个部分开始到哪个部分,是一个完整的应用层数据包。

        2.9.1 如何避免粘包问题呢?

        归根结底就是一句话,明确两个包之间的边界。

        对于定长的包,保证每次都按固定大小读取即可。

        对于变长的包,可以在报头位置,约定一个包总长度的字段,从而就知道了包的结束位置。

        对于边长的包,还可以在包和包之间使用明确的分隔符。

        2.9.2 UDP 会存在粘包问题吗?

        UDP 是一种无连接的传输协议,不会对数据包进行拆分和合并,因此不存在 TCP 中的粘包问题。每个 UDP 数据包都是独立的,不会因为传输过程中被合并或拆分而导致粘包问题。

        2.10 异常情况

        1)进程终止:进程终止会释放文件描述符,操作系统仍然可以发送 FIN ,和正常关闭没有什么区别。当一个端口上的所有数据都发送完毕后,操作系统会自动发送一个 FIN 段,用来通知另一端数据发送完毕并准备关闭连接。

        2)机器重启:和进程终止的情况相同。

        3)机器掉电/网络断开:接收端认为连接还在,一旦接收端有写入操作,接收端发现连接已经不在了,就会进行 RESET ,即使没有写入操作,TCP 自己也会内置一个保活定时器,会定期询问对方是否还在,如果对方不在,也会把连接释放。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【C++】priority_queues(优先级队列)和反向迭代器适配器的实现

目录 一、 priority_queue1.priority_queue的介绍2.priority_queue的使用2.1、接口使用说明2.2、优先级队列的使用样例 3.priority_queue的底层实现3.1、库里面关于priority_queue的定义3.2、仿函数1.什么是仿函数?2.仿函数样例 3.3、实现优先级队列1. 1.0版本的实现…

DGC-GNN 配置运行

算法 DGC-GNN,这是一种全局到局部的图神经网络,用于提高图像中2D关键点与场景的稀疏3D点云的匹配精度。与依赖视觉描述符的方法相比,这种方法具有较低的内存需求,更好的隐私保护,并减少了对昂贵3D模型维护的需求。DGC-…

树莓派发送指令控制FPGA板子上的流水灯程序

文章目录 前言一、树莓派简介二、整体实现步骤三、树莓派设置四、树莓派串口代码五、Verilog代码5.1 串口接收模块5.2 流水灯模块 六、quartus引脚绑定七、 运行效果总结参考 前言 ​ 本次实验的目的是通过树莓派和FPGA之间的串口通信,控制FPGA开发板上的小灯。实验…

LBSS84LT1G 130MA 50V P沟道小电流MOS管

LBSS84LT1G作为一款P沟道功率MOSFET,由于其低导通电阻和快速切换特性,在电机控制中有着广泛的应用。以下是几个典型的应用案例: 1. 直流电机驱动:在直流电机驱动电路中,LBSS84LT1G可用于控制电机的转速和方向。通过控…

WebSocket前后端建立以及使用

1、什么是WebSocket WebSocket 是一种在 Web 应用程序中实现双向通信的协议。它提供了一种持久化的连接,允许服务器主动向客户端推送数据,同时也允许客户端向服务器发送数据,实现了实时的双向通信。 这部分直接说你可能听不懂;我…

nestJs中跨库查询

app.module.ts中配置 模块的module中 注意实体类在写的时候和数据库中的表名一样 service中使用一下

【Cesium解读】Cesium中primitive/entity贴地

官方案例 Cesium Sandcastle Cesium Sandcastle 好文推荐:Cesium贴地设置_primitive贴地-CSDN博客 scene.globe.depthTestAgainstTerrain true; True if primitives such as billboards, polylines, labels, etc. should be depth-tested against the terrain…

【C++】内联函数、auto、范围for

文章目录 1.内联函数2.auto关键字2.1auto简介2.2auto的注意事项2.3auto不能推导的场景 3.基于范围的for循环(C11)4.指针空值nullptr(C11) 1.内联函数 概念: 以inline修饰的函数叫做内联函数,编译时C编译器会在调用内联函数的地方展开,没有函…

CLIPDraw:通过语言-图像编码器探索文本到绘图合成

摘要 本工作介绍了 CLIPDraw,这是一种基于自然语言输入合成新颖绘画的算法。CLIPDraw 不需要任何训练;相反,它使用了一个预先训练好的 CLIP 语言-图像编码器作为衡量标准,以最大化给定描述与生成绘画之间的相似度。关键的是&…

使用XxlCrawler抓取全球航空公司ICAO三字码

目录 前言 一、数据源介绍 1、目标网站 2、页面渲染结构 二、XxlCrawler信息获取 1、创建XxlCrawler对象 2、定义PageVo对象 3、直接PageVO解析 4、自定义解析 总结 前言 长距离旅行或者出差,飞机一定是出行的必备方式。对于旅行达人或者出差人员而言&…

为什么使用AI 在游戏中不犯法

使用AI在游戏中本身并不违法,甚至在很多情况下,游戏公司自己也会在游戏中集成AI来提高游戏体验,例如通过AI驱动的非玩家角色(NPC)来增加游戏的互动性和挑战性。然而,使用AI是否违法取决于AI的使用方式和目的…

轻松掌握抖音自动点赞技巧,快速吸粉

在当今这个信息爆炸的时代,抖音作为短视频领域的领头羊,不仅汇聚了庞大的用户群体,也成为了品牌和个人展示自我、吸引粉丝的重要平台。如何在众多内容创作者中脱颖而出,实现高效引流获客,精准推广自己的内容&#xff0…

Context Pattern上下文模式

使用情景 全局使用的配置,数据库的连接。MVC中的跨层数据传输携带请求ID,用户信息等用户权限信息线程上下文 跨层数据共享 统一调用参数 携带多个事务需要处理的对象 携带用户信息 使用ThreadLocal

项目-坦克大战-让坦克动起来

为什么写这个项目 好玩涉及到java各个方面的技术 1,java面向对象 2,多线程 3,文件i/o操作 4,数据库巩固知识 java绘图坐标体系 坐标体系-介绍 坐标体系-像素 计算机在屏幕上显示的内容都是由屏幕上的每一个像素组成的像素是一…

drippingblues 靶机实战

信息收集: Nmap: 存活: 靶机ip:192.168.10.110 端口: 服务: 发现ftp服务可以匿名登录。且用户名是FTP。 发现一个压缩包,下载并爆破。 得到密码 072528035。发现关键字 drip。里面还有一个 secret.zip(…

GIT基础01 基础命令与分支

前言 我们知道git是开发中比较常见的版本控制工具 我们可以先提出一个场景: 老板让你去修改方案 第一次修改 打回 第二次修改 打回 第n次修改 老板让你使用第一次的版本 阁下如何应对??? 我对每个版本进行编号?? 是一种方案 但是这里也是有缺陷的 比如说在很多版本中找…

将 Vue、React、Angular、HTML 等一键打包成 macOS 和 Windows 平台客户端应用

应用简介 PPX 基于 pywebview 和 PyInstaller 框架,构建 macOS 和 Windows 平台的客户端。本应用的视图层支持 Vue、React、Angular、HTML 中的任意一种,业务层支持 Python 脚本。考虑到某些生物计算场景数据量大,数据私密,因此将…

odoo16 银行对账单导入改造

解决问题: odoo原生功能的话 是不能在系统上临时处理文件内容的,只会提示文件内容格式不对。 原始文件格式 在头部与尾部 格式问题,例如csv文件和 C53 文件,做一个前置弹框处理数据之后再导入 camt效果: csv效果:

Ajax额

原生Ajax xml 已被json取代 http 请求方法urlhttp版本号 network 谷歌浏览器查看请求报文和响应报文 F12 network header里面有 请求头 响应头 点击view source 可以查看请求响应行 请求体在请求行头下面 get请求有url参数,请求体变为query String…