TCP为什么会出现粘包现象

news/2024/5/18 15:59:43 标签: tcp/ip, udp

粘包关系最大的就是基于字节流这个特点。

字节流可以理解为一个双向的通道里流淌的数据,这个数据其实就是我们常说的二进制数据,简单来说就是一大堆 01 串。这些 01 串之间没有任何边界

图片

应用层传到 TCP 协议的数据,不是以消息报为单位向目的主机发送,而是以字节流的方式发送到下游,这些数据可能被切割和组装成各种数据包,接收端收到这些数据包后没有正确还原原来的消息,因此出现粘包现象。

为什么要组装发送的数据?

我们知道TCP 切割数据包是为了能顺利通过网络这根水管。相反,还有一个组装的情况。如果前后两次 TCP 发的数据都远小于 MSS,比如就几个字节,每次都单独发送这几个字节,就比较浪费网络 io 。

图片

所以就有了 Nagle 算法优化,目的是为了避免发送小的数据包。

在 Nagle 算法开启的状态下,数据包在以下两个情况会被发送:

  • 如果包长度达到MSS(或含有Fin包),立刻发送,否则等待下一个包到来;如果下一包到来后两个包的总长度超过MSS的话,就会进行拆分发送;

  • 等待超时(一般为200ms),第一个包没到MSS长度,但是又迟迟等不到第二个包的到来,则立即发送。

此时发送的这些数据包都是一整个 01 串,如果处理开发者把第一次收到的 msg1 + msg2 就当做是一个完整消息进行处理,就会看上去就像是两个包粘在一起,就会导致粘包问题

关掉Nagle算法就不会粘包了吗?

Nagle 算法其实是个有些年代的东西了,诞生于 1984 年。对于应用程序一次发送一字节数据的场景,如果没有 Nagle 的优化,这样的包立马就发出去了,会导致网络由于太多的包而过载。

但是今天网络环境比以前好太多,Nagle 的优化帮助就没那么大了。而且它的延迟发送,有时候还可能导致调用延时变大,比如打游戏的时候,你操作如此丝滑,但却因为 Nagle 算法延迟发送导致慢了一拍,就问你难受不难受。

所以现在一般也会把它关掉

看起来,Nagle 算法的优化作用貌似不大,还会导致粘包"问题"。那么是不是关掉这个算法就可以解决掉这个粘包"问题"呢?

TCP_NODELAY = 1

图片

关闭Nagle就不会粘包了吗

  • 接受端应用层在收到 msg1 时立马就取走了,那此时 msg1 没粘包问题

  • **msg2 **到了后,应用层在忙,没来得及取走,就呆在 TCP Recv Buffer 中了

  • **msg3 **此时也到了,跟 msg2 和 msg3 一起放在了 TCP Recv Buffer 中

  • 这时候应用层忙完了,来取数据,图里是两个颜色作区分,但实际场景中都是 01 串,此时一起取走,发现还是粘包。

因此,就算关闭 Nagle 算法,接收数据端的应用层没有及时读取 TCP Recv Buffer 中的数据,还是会发生粘包。

 


http://www.niftyadmin.cn/n/1629030.html

相关文章

云硬盘的基本操作

目前这个操作系统里面一共挂载了多少个云硬盘?用fdisk -l查看一下。 /dev/vdb,上章节新购买的云盘。 现在针对这块云硬盘vdc进行分区操作。先使用比较传统的MBR方式进行分区。 起始扇区2048,结束扇区20971519,已创建分区表并且同步…

Java总结篇系列:类型转换/造型

Java中,经常可以遇到类型转换的场景,从变量的定义到复制、数值变量的计算到方法的参数传递、基类与派生类间的造型等,随处可见类型转换的身影。Java中的类型转换在Java编码中具有重要的作用。首先,来了解下数据类型的基本理解&…

网络层对数据进行切片后会出现粘包问题吗?

IP 层会对大包进行切片,是不是也有粘包问题? 先说结论,不会。首先前文提到了,粘包其实是由于使用者无法正确区分消息边界导致的一个问题。 先看看 IP 层的切片分包是怎么回事。 P分包与重组 如果消息过长,IP层会按 M…

CentOS 7上VNCServer的安装使用

1、安装 yum install tigervnc tigervnc-server2、配置 vncserver的配置,创建一个新的配置文件 cp /lib/systemd/system/vncserver.service /lib/systemd/system/vncserver:1.service编辑/lib/systemd/system/vncserver:1.service vim /lib/systemd/system/vncserve…

力扣刷题续

79.实现strStr(KMP) 方法一 .常规方法 class Solution { public:int strStr(string haystack, string needle) {if(haystack.empty() && needle.empty()) return 0;int m haystack.length();int n needle.length();for(int i0;in<m;i){bool flag true;for(int …

衬线字体和非衬线字体区别

衬线字体和非衬线字体区别 一、总结 1、衬线字体&#xff08;宋体&#xff09;&#xff1a;见名知意&#xff0c;就是比划有粗有细&#xff0c;非衬线字体所以字的所有比划的都是一样粗细&#xff08;幼圆&#xff09; 二、衬线字体和非衬线字体区别 衬线体棱角分明&#xff0c…

分布式缓存--系列1 -- Hash环/一致性Hash原理

当前&#xff0c;Memcached、Redis这类分布式kv缓存已经非常普遍。从本篇开始&#xff0c;本系列将分析分布式缓存相关的原理、使用策略和最佳实践。 我们知道Memcached的分布式其实是一种“伪分布式”&#xff0c;也就是它的服务器结点之间其实是相互无关联的&#xff0c;之间…

strcpy,memcpy以及mommove的实现

一、strcpy&#xff08;只适用于字符串&#xff09; strcpy在进行字符串拷贝时&#xff0c;会将\0字符一同拷贝过去。 除了内存重叠&#xff0c;strcpy函数还有一个弊端&#xff1a;如果目的地址分配的长度小于源地址的要拷贝的数据的长度&#xff0c;那么会发生越界&#xf…