文章地址:TCP 粘包? TCP 警察什么梗
从 v2 学到很多,按照自己理解总结了下。0.0

讲拆包粘包的很大比例是 Javer ,Netty 权威指南功不可没…

TCP 粘包?伪命题,tcp 从来不是像 UDP 一样,以包设计的,而是流式的,就像滔滔不绝的流水一样。

有请双方选手入...哦 2L 已经入场一位!

好久没有这个话题了,恭喜 lz 找到了热点

警察看了头疼

粘包一词到底是怎么造出来的,我很是好奇

PS 每每看到粘包警察一词就想笑

粘念 zhān 还是 nián ?

原封不动的把一篇文章看完了,耗时 10 分钟。

警察已经开始摆烂了

TCP 粘包是啥? 自己创造一个名词出来? TCP 从来没有粘包一说, 看你的文章你也是对 TCP 一知半解。 麻烦赶紧删了,免得误人子弟。
我先跟你说,很明确的来说 TCP 没有粘包这一个说法,根本就不存在。
我看你用 Java 写的代码, 那么我就用 Java 代码给你举个例子

Socket socket = new Socket("127.0.0.1", 8000);
OutputStream os = socket.getOutputStream();
os.write("test".getBytes());

实际上会发生什么?
如果网络延迟,或则发生丢包,那么会超时重传. 然后网络线路没问题, 那么会直接写入系统的 TCP/IP buffer 里面去。

如下

Socket socket = new Socket("127.0.0.1", 8000);
OutputStream os = socket.getOutputStream();
os.write("test".getBytes());
os.write("test1".getBytes());
os.write("test3".getBytes());

那么我写入三次表示什么? 很显然根据我上面说的,系统为了性能会缓存对应的 TCP/IP 的数据信息, 那么我可以采用一个很大 buffer 来进行一次性将这两次的请求给直接读取过来。

根据这个理解那么就可以把 TCP 看作流, 通过流来进行运输货物,很显然明显的是 TCP 就是流协议。 流协议何谈封包和拆包?
那如何解决判断 TCP 中这次请求的信息已经是末端了?
很常见的两种方案

  1. 一次请求一次响应, 后续关掉 socks
  2. 用 4 字节定义一个无符号的整数来定义这个报文的 Length 就好了

所谓的 特殊分隔符简直是最愚蠢的做法, 难道我的报文中就不能出现对应的特殊符号吗? 固定消息长度 简直是浪费内存和网络开销。完全不可取。

因为是流协议, 所以需要应用自己去判断写入的字节什么时候已经达到的末端。

其实这块儿的中文术语很模糊,报文、帧、数据包啥的,用英文表达会好一点。

有的书把 packet 翻译成报文,有的把 message 翻译成报文,服了…

建议 op 看看
draveness.me/whys-the-design-tcp-message-frame/

热帖预订。顺便提示楼主,还有一个流量密码:HTTP 状态码一律 200 、HTTP 请求方式一律 GET/POST

无所谓了,只要你能听明白, 需要一个上层协议来拆分信息就行

前一阵子有个沙雕,非要我发送的时候,给他拆好 .dog

我接收的怎么是这样子 .jpg
你那里有问题 .jpg
不是我的问题 .jpg
不是我负责的 .jpg
你前端改改 .jpg

TCP: 我把东西按顺序给到你了,我们也不知道你们发的啥玩意儿,自己看吧

当我看到 TCP 粘包的时候,我很震惊, 后面我开始解释 TCP 没有粘包, 只有 “因为是流协议, 所以需要应用自己去判断写入的字节什么时候已经达到的末端。” 后来我渐渐的麻木......

TCP 粘包就是理论上不存在但实际上必须处理的东西 /狗头

这页面上乱七八糟的元素,我还以为我打开了内容农场

死去的回忆开始攻击我

packet frame message
跨频道聊天是吧

四层传输层 TCP 协议流式,七层应用层通过缓冲区映射成数据包处理,说粘包并没错。但是“粘包”这个词是生造的,用于新手快速理解还可以,再深入点就该换成“分帧取帧”,或者“帧解码”。

#21 你确定你理解的是楼主所说的问题, TCP 帧在应用层是不关心的。 而所谓的 “判断写入的字节什么时候已经达到的末端” 是需要自己解析的
而且你说的 “分帧取帧”,或者“帧解码”。 是指什么? 说的是 解析 RFC 793 里面的 TCP Header Format 吗? 很抱歉,在用户使用协议上,没有权限读取对应的 TCP Header Format , 要么使用 tun/tap 等虚拟网卡, 要么使用 pcap/winpcap/npcap 或则 win10 的驱动网络拦截。 但是这些 TCP 协议的操作,往往都不是 TCP 使用用户来进行操作的, 楼主很明显是在使用 TCP 协议, 而不是解析 TCP 协议

什么叫字节文化啊(后仰

HTTP1.0 好像就是根据 connection:close ,来判断 HTML 是否已经完全传输完毕。

也不是所有的 TCP 都有 content-length 属性,在那个 IE 时代,经常遇见下载到一半的网页突然断开。

在 TCP 这层不用考虑这个

TCP 有所谓的“粘包”是使用情景出错了,你把两个以上的数据报放在一个 tcp 流里面传输了;正常的应该是一个“包”一个连接。像 HTTP 的长连接就是这种情况,不过 HTTP header 有 length 可以解决“粘包”

#22 网络通信是七层,不要死扣在传输层 TCP 协议这一个上。帧的英文是 Frame 。还有不要再回复了,这贴是给楼主的内容农场引流的,正方反方意见都不重要,都会给楼主引流。

他们说的 tcp 粘包,应该是指 nagle 算法吧。。

/go/water

TCP 没有包,但是这篇文章非要把指出这个事实的人扣一个“粘包警察”的帽子,似乎还有点得意。
基于错误的概念讨论一大堆东西都是没有意义的。
就这篇文章来说,TCP 的包是啥它自己清楚吗?
是你调用一次 socket write 的数据,还是 wireshark 抓包看到的一个 TCP 的条目?还是你应用层自己定义的逻辑结构?
概念都不定义清楚就自说自话,就是一堆废话。

掘金在某些人看来已经是内容农场了么 哈哈哈
国内要啥社区生态啊

就喜欢看这种话题,掐!打起来!别停手!
小马扎、花生米已经就位啦!

奥山 YY 来人

之前也看过很火的几个黏包警察的帖子
面试的时候也被问过 大概就是解决黏包的方案 比如 [content]

其实说的不是报文粘包,而是消息解析的问题

我不管,我的 TCP 就是要粘包[手动狗头]

TCP 只保证可靠数据传输,没说把数据一个个拆开好给你,这件事应该由上层协议负责处理。
如果是这样的话,你也可以提出这样一系列问题:
如何解决 IP 协议不能可靠数据传输的问题?常规解决方案是用 TCP ;
如何解决 Ethernet 协议与全球服务节点连接问题?常规解决方案是使用 IP 协议;
...
回过头来看,这正是「分层」思想的奥义所在啊,每一层只处理好自己的事儿。

·粘包·真是误人子弟,还有一大堆捧的,还在那里抠概念,错的就是错的

和 nagle 没任何关系。无论怎样,接收端读都可能会读取不定次数写的内容。

我无法理解这里在嘲讽 tcp 粘包的什么问题。这确实是工程中需要处理的内容。

这解释到位,可以。

好几年前我一直认为 tcp 粘包是一个非常复杂的事情,一直没认真去看,后来要面试就专门去看 TCP 粘包。tmad 差点颠覆我的认知,这算个屁粘包,不知道哪个土鸡 提出来的。后来终于看到 V2 原来也有很多人不认可这个事情,那我就放心了,原来我的认知没错,某些人的问题。。。

生造词只会把问题弄得更复杂,明明很简单的原理,一句话就能说清楚的事情,非要生造一个词,然后再写一篇文章来解释这个词,把问题弄得更复杂。
还有,你说人家是“tcp 警察”,我觉得你是“tcp 恐怖分子”

#1 javer 表示不背这个锅

tcp 流式传输哪来的包, 脑袋里长了个包吗...

这种情况也不能叫 tcp 粘包, 叫应用层粘包才对.

这就是中文 cs 界的恶心之处,总是发明一些莫名奇怪的称呼。英文 tcp framing tcp stream 就很直观

十年前看网络编程书籍的时候有“tcp 粘包”的说法,其实是说需要一个业务协议去分包,比如:length + body 的格式,懂得都懂,每天没事做就拿出来喷一次,何必呢

粘包 难道不是“碰瓷”的意思? emmmm, 这个标题我都没看懂......TCP 警察......你再说某夫网?

早上看到帖子乐了,以为大家会调侃一下粘包警察的耿
结果。。哈哈哈

看到“TCP 粘包”这个专有名词,我表示极度震惊。连夜打车回到家里,战战兢兢翻开《计算机网络》,拿着放大镜仔细看了半夜,也没看到“粘包”两个字。我的后背不觉地渗出致密的汗水,双手止不住地发抖。匆忙打开电脑,一篇篇地翻着论文,试图寻找关于这个词的信息。可眼看天就要亮了,我依旧一无所获。我失望的躺在床上,满脑子都是“粘包,粘包,粘包!”,横竖睡不着,不得已打开了知乎,写下了一个问题“究竟什么是 TCP 粘包”。不一会儿答案就如雪花儿般涌了出来,每一片雪花上都写着一句话“TCP 没有粘包”。我颤抖的双手终于停了下来,一股热流从我心底涌到泪腺。啊,原来我并不孤独。

讨论一个东西的前提是得有定义,谁来定义这个 TCP 的包概念?其次,同样是流式读写,没有人会在读写文件的时候说有粘包问题吧?

哈哈哈哈,每年都有几次粘豆包。[头秃]

建议粘豆包用户都改用 websocket

掘金已经和内容农村差不多烂了

某种意义来说,楼主已经成功了,确实吵起来了 (doge

#7 nian 是形容词,大 nian 鼻涕;
zhan 鼻涕 zhan 手上甩不下来; zhan 胶带。
所以应该是 zhan 包,
nian 豆包

TCP 确实有“粘包”问题。

所以为什么要死磕 TCP ?找个 TCP 上层的、有“消息”概念的协议不好嘛?比如 WebSocket ?

我有些反感粘包警察,是因为早就被标准化解决了无数遍,直接拿来就能用(比如 WebSocket 这个五层协议)的问题,非要当做现实中一个重大问题去翻来覆去地讨论。

分包组包这是网络层干的事情, 跟传输层有什么关系.
看 ip 协议有个分包组包, 然后造个 tcp 的拆包黏包, 真的是恶心啊, 很容易把基础不行的人带歪.

#56 tcp 都没有包这个概念, 怎么会 粘和拆 呢

nnmlgbb

WebSocket 属于第五层?那么为什么握手要基于 HTTP 。

搜了下,OP 文章提的都是网络上很多年就有的名词和争议, 怎么都在骂楼主扣帽子。。

不是看起来是,而是他已经在朝这方面做,用 Google 搜一下 site:juejin.cn inurl:/s/ 你就能体验到了

嗯我确实说错了,在通用模型里面属于第四层应用层。HTTP 和 WebSocket 都属于应用层。

另外如果看 HTTP 和 WebSocket 的关系,实际上 WebSocket 可以独立于传统的 HTTP 服务器单独使用,只不过 Handshake 这一步好像用了 HTTP header 。但如果一整个端口都用于 WebSocket 应用程序的话,其实可以忽略 HTTP 协议这玩意儿。

WebSocket 单独使用,你可以参考币的交易所协议。

吗吗,你的言论有些“反粘包警察”哦。

所以其实我“粘包”打引号了。虽然 TCP 确实不存在粘包这个概念,但是在应用中这个“问题”确实存在。我是不关心这玩意儿到底用“粘包”这个术语,还是准确地“因为 TCP 是流式协议所以必须自己处理数据包分割的问题”这么长的文本描述。在我看来,入乡随俗,如果“粘包”接受度广,用“粘包”来代指上面这句话我没意见。

http 1.0 是靠 tcp connection close 来识别的; 1.1 才有 content-length 和 transfer-encoding chunked 这两个功能

谷歌翻译给这个字的音标是 /Zhān/,点发音念的是 nian ,笑死了

#64 所以如果叫 基于 tcp 传输的应用层消息拆分 我是没意见的, 非要叫个 tcp 拆包, 纯属误人子弟

诶?难道不是吗?

“你们不要再打了啦”

#64
我告诉你粘包是怎么来的

Socket socket = new Socket("127.0.0.1", 8000);
OutputStream os = socket.getOutputStream();
os.write("test".getBytes());
os.write("test1".getBytes());
os.write("test3".getBytes());

写了三次数据, 然后在调用 read 读取的时候发现写入的数据被一次性读取到了, 所以他 /她认为数据包被粘连在一起了。
“粘包” 无论是否打引号说出这个词就是对 TCP 协议的不理解,想当然的一个词语。 这种本身就应该抵制。"需要自己判断写入的字节什么时候已经达到的末端", 这就很好的解释了这个问题。
我没猜错你对 TCP 协议估计也是一知半解 。你写一次 tun 设备的 三次握手和四次挥手, 你就知道所谓的封包 /拆包 /重传 等等, 都已经做好, 数据已经有序的给你了。 你只要操作 Stream 就可以了。

我在跟你明确一下, 他说的粘包,指的是 代码中 write 两次, 另一端 read 一次的时候就可以读出来。
或则我这么问你, 如果你发现 TCP 有所谓的粘包, 请截图用 wireshark 抓包并且保存截图让我看看, 你能截屏出来, 我给你奖励 1w

把协议设计好基本不会出现所谓的“粘包”

#敏感词 有没有可能,你说的这个东西接受度最广的叫法是「协议」。

查重率百分之百

所谓的 特殊分隔符简直是最愚蠢的做法
http header 就是靠\n\n....

所谓“粘包问题”不就是设计一个应用层协议的问题么?在 TCP 协议(传输层)的范畴中,问题不存在就不是不存在...

我不否认粘包实际不存在。我知道 TCP/IP 。但我觉得既然这么多人叫,那在别人都这么叫的语境下,借用这个术语表达他们的意思,我没意见。。。

为啥要这么纠结术语的纯洁性。DL 论文里面一堆(数学)术语乱用,只要该 domain 认同,不也就这么过来了。

不知道在吵吵啥,听得懂就行,非 BB 半天你这概念不对,描述不对

/t/876279

http 是靠\r\n\r\n 吧。不是\n\n 吧?

别纠结“粘包”这个词翻译对不对,令我震惊的是大多数人好像都不知道这回事

不用'特殊分隔符'的话,还有其他好法子吗?

TCP 粘包,UDP 汤包,ICMP 叉烧包

那 tcp 没有粘包,upd 也没有粘包,粘包这个词是怎么来的?😵

#74L
我从未听过 http 协议中用 \n\n 来最为判断文本已经达到的末端。 根据 http 协议 content-length 用来判断数据大小是多少, 即使在早期也是 一次请求,一次响应, 用 tcp connection close 来识别的。 请问你说 的 \n\n 是哪个版本?

#83
说白了就是没有了解 tcp 的原理,没有了解流的概念,导致了 “发送两次,却一次就能全接收了”。
也就是 “我明明辛辛苦苦把数据分成两次(“他认为这是两个包”)发送,怎么一次就全接收了,肯定是 tcp 协议把我的两个 ‘包’ 粘在一起了” ,所以有了 “tcp 粘包” 这个概念。但是对于 tcp 来说是没有包的这个概念的,是发明 “粘包” 的这个人没有了解 tcp 原理导致的。
同理,如果一个人只知道流,没有包的概念,那他遇见 udp 就会产生“udp 拆包”,tcp 是保证顺序的,udp 不保证,他还会产生“udp 乱流”的概念,因为不知道一个东西怎么用就强行用会导致无数个“xx 问题”的概念,但是这些概念本身没有什么意义,因为如果一开始就了解一下什么是流,“粘包”这个概念根本就不会产生。

楼上有人纠正过了,是\r\n\r\n.... 这个分隔符用来分割 http header 的 content 的

一个个都在 纠正 TCP 没有粘包, 我看了就头疼,为什么你们接受不了这个形容词呢? 如果你们要纠正,那就请你拿出正确的形容词出来(必须是业内认可,通用的,不能是自己造的)。

无论你们认不认,有一个事实 已经是既定的了, 那就是听到 TCP 粘包,大家就知道 是接收端 读到了数据,但是数据里 不止一条消息,需要自己去拆分出来。 粘包这个形容词 已经是业内通用了的, 你们非要来纠正,但是又拿不出真正通用的 形容词。

恕我直言,这种行为叫抬杠。

正确的叫法是“一种对协议进行错误解析的方式”