Java中的TCP协议(如果想知道Java中有关TCP协议的知识,那么只看这一篇就足够了!)(下)
前言:TCP协议是网络通信的基础,其提供可靠、面向连接的数据传输,确保数据包按序到达且无丢失,TCP 广泛应用于文件传输、即时通讯和 Web 服务,是我们在学习网络编程的重要基础。
✨✨✨这里是秋刀鱼不做梦的BLOG
✨✨✨想要了解更多内容可以访问我的主页秋刀鱼不做梦-CSDN博客
在正式开始讲解之前,先让我们看一下本文大致的讲解内容:
目录
1.滑动窗口
2.流量控制
3.拥塞控制
(1)慢启动
(2)拥塞避免
(3)快重传
(4)快恢复
4.延迟应答
5.捎带应答
6.TCP粘包问题
(1)TCP粘包简介
(2)粘包问题的产生原因
(3)案例
(4)TCP粘包问题的解决方法
1.滑动窗口
概念:
滑动窗口机制允许发送方在未收到 ACK 之前,连续发送多个数据包,从而提高吞吐量,而不是每发送一个数据包都必须等待 ACK。
未使用滑动窗口的情况:
使用滑动窗口的情况:
我们可以发现使用了滑动窗口之后,其效率会大大的提升!
——在初步了解了滑动窗口的定义之后,让我们看一下滑动窗口中的基本概念:
发送窗口:发送方可以连续发送的数据量,单位为字节,而窗口大小由接收方的可用缓冲区大小决定。
接收窗口:接收方能接收的数据量,超过此窗口的数据将会被丢弃或缓存。
确认窗口:接收方已成功接收的数据范围,收到 ACK 后窗口前移。
——那么滑动窗口又是如果工作执行的呢?
这里我们假设滑动窗口大小 W = 3,发送方会按照以下步骤发送数据:
发送方连续发送 Data1、Data2、Data3数据,然后等待 ACK。
接收方收到数据后,返回 ACK1、ACK2、ACK3,表明 Data1、Data2、Data3数据 均被接收到了。
发送方窗口前移,继续发送 Data4、Data5、Data6数据。
滑动窗口机制相比于逐个确认的方式,提高了数据传输效率,减少了等待时间!!!
——至此我们就大致的了解了什么是滑动窗口已经其工作流程了!
2.流量控制
概念:
流量控制的目标是防止发送方发送数据过快,以至于接收方无法处理,TCP通过接收窗口来动态调整发送方的速率。
——了解了流量控制的概念了,那么其执行机制又是怎么样的呢?
其具体机制:
接收方在 ACK 中返回接收窗口的大小,通知发送方自己还有多少缓冲区可以接收数据。
发送方根据接收窗口的大小进行调整:
如果接收窗口的大小变小,则发送方减少发送速率,避免接收方溢出。
如果接收窗口的大小变大,则发送方可以提高发送速率,提高吞吐量。
当然说到流量控制,我们就不得不说一下零窗口问题:
如果接收方的接收窗口的大小等于0,那么就表示它的缓冲区已满,发送方必须暂停发送,进入零窗口等待,此时:
发送方会周期性发送探测报文,询问接收方是否可以继续发送数据。
当接收方缓冲区恢复可用时,就会发送新的 ACK,通知发送方窗口大小,允许继续发送。
3.拥塞控制
概念:
拥塞控制是用来防止网络因过载而丢包、从而延迟增加,其核心目标是优化带宽使用,同时避免网络拥塞。
其机制主要包含慢启动、拥塞避免、快重传、快恢复四个阶段,那么接下来让我们分别看一下这四个阶段:
(1)慢启动
慢启动阶段用于逐步探测网络带宽上限,防止发送方一开始发送过多数据导致网络拥塞。
其工作方式:
初始状态:
cwnd = 1 MSS
(最大分段大小)。指数增长:每收到一个 ACK,
cwnd
翻倍:
发送 1 个数据包,收到 ACK 后
cwnd = 2 MSS
。发送 2 个数据包,收到 ACK 后
cwnd = 4 MSS
。发送 4 个数据包,收到 ACK 后
cwnd = 8 MSS
。直到
cwnd
达到ssthresh
后,进入拥塞避免阶段。
(2)拥塞避免
其工作方式:
当
cwnd
超过ssthresh
后,TCP 进入线性增长阶段,cwnd
每个 RTT 只增加1 MSS
,而不是指数增长
(3)快重传
当 TCP 发送方收到3 个重复的 ACK时,其会立即重传丢失的数据包,不会等待超时。
(4)快恢复
其工作方式:
在快重传后,TCP会假设网络没有完全拥塞,只是部分丢包。
cwnd
被调整为ssthresh / 2
,然后进入拥塞避免阶段
以上就是拥塞控制的四个阶段介绍了。
4.延迟应答
概念:
延迟应答的策略是在接收到数据后,等待一小段时间(通常是 200ms 左右),看看是否有需要一起发送的数据,如果有,就将ACK与数据一起发送,如果没有再单独发送ACK。
那么其又是如果工作的呢?
延迟应答的具体工作方式如下:
当接收方收到一个TCP数据包时,它不会立即返回ACK,而是启动一个短暂的计时器。
如果在计时器到期前,接收方需要发送数据给发送方,那么ACK就会被“合并”到数据包中一起发送,从而减少一个单独的ACK包。
如果在计时器到期前没有数据要发送,接收方就会单独发送ACK。
以上就是延时应答的全部内容了!!
5.捎带应答
捎带应答的原理是在发送数据时顺便携带ACK信息,而不是单独发送ACK包,它的核心思想是利用数据包的发送机会,在数据包的标头中附加ACK信息,从而减少独立的ACK数据包的数量。
那么它又是如果工作的呢?
A 发送一个 TCP 数据包给 B。
B 需要回复 A 数据,同时本应发送的 ACK 也可以捎带在这个数据包的 TCP 头部。
当A 在收到 B 的数据包时,其就即得到了数据,又得到了 ACK。
在了解完了其工作原理之后,我们再来了解一下其适用的场景:
以上就是携带应答的全部内容了!!
6.TCP粘包问题
最后,让我们讲解一下TCP的粘包问题,首先先让我们了解一下什么是TCP粘包问题:
(1)TCP粘包简介
TCP粘包问题指的是接收方一次接收到的数据包含了多个发送方发送的包数据,其边界不清晰,这就会导致接收方不知道该读取到哪里
(2)粘包问题的产生原因
那么为什么会产生粘包问题呢?首先TCP 是一个 面向字节流 的协议,所谓的粘与拆问题,其实就是因为TCP 只保证字节流的可靠和顺序,不关心数据包的边界所导致的。
而粘包的问题主要有两方面的原因:
发送端的原因:
应用程序连续调用多次
write
操作,会将多段数据发出。TCP 会将多次写入的数据合并成一个大的数据块进行发送,以减少发送次数,但这促使了粘包问题的产生
接收端的原因:
接收方的应用程序每调用一次
read
操作时,不一定能完整接收到一个业务数据包。接收方可能一次性收到了多个业务数据包的数据,也可能收到一个包的一部分,这取决于内核缓冲区的数据情况和接收时机。
通过上述的介绍,我相信读者对于TCP粘包问题有了一定的理解了,但是可能还是有些模糊,这里我们使用一个案例来帮助读者你更好的进行理解。
(3)案例
我们假设客户端连续发送两条消息,第一条是 Hello,第二条是 World,但由于 TCP 是字节流传输,它不会按照你发的次序发送,其可能会合并成一块发出去,此时服务端收到的是数据就会是 HelloWorld
,这是“粘包”,但是拆包时,我们可以将其拆成几次发的,比如先收到 Hel,再收到 loWo,最后收到 rld,这是“拆包”,这就导致服务端无法判断一条消息的开始和结束。
为了解决这个问题,我们通常会在每条消息前面加一个“长度字段”,告诉服务端这条消息有多长,比如 [5]Hello[5]World,这样服务端就能正确读取每条消息了
希望读者根据上述的案例,能更好的理解TCP粘包问题。
(4)TCP粘包问题的解决方法
了解了什么是粘包问题之后,那么怎么对该问题进行解决呢?主流的解决方式大致有以下三种:
1. 定长协议
——给每个数据包规定长度,比如每个数据包 100 字节,接收方每次读取 100 字节进行处理。
2. 添加分隔符
——在每个数据包末尾加一个特殊字符(如
或自定义标志位)作为分隔。
3. 包头 + 包体
——在每个数据包前加一个固定长度的“包头”,包头中包含整个包的长度字段,接收方先读取包头,然后根据包头中的长度读取完整数据包。
至此我们就学习完了TCP粘包问题了!
以上就是本篇文章的全部信息了!!!