文章地址:TCP 粘包? TCP 警察什么梗
从 v2 学到很多,按照自己理解总结了下。0.0
1
zjp 2022-08-29 08:49:26 +08:00 via Android
讲拆包粘包的很大比例是 Javer ,Netty 权威指南功不可没…
|
2
jiulang 2022-08-29 08:52:01 +08:00 8
TCP 粘包?伪命题,tcp 从来不是像 UDP 一样,以包设计的,而是流式的,就像滔滔不绝的流水一样。
|
3
RRyo 2022-08-29 08:54:00 +08:00 15
有请双方选手入...哦 2L 已经入场一位!
|
4
winterbells 2022-08-29 08:56:55 +08:00 1
好久没有这个话题了,恭喜 lz 找到了热点
|
5
wanguorui123 2022-08-29 08:59:12 +08:00
警察看了头疼
|
6
mywaiting 2022-08-29 09:08:33 +08:00 1
粘包一词到底是怎么造出来的,我很是好奇
PS 每每看到粘包警察一词就想笑 |
7
TWorldIsNButThis 2022-08-29 09:11:28 +08:00 via iPhone 15
粘念 zhān 还是 nián ?
|
8
xlsepiphone 2022-08-29 09:12:42 +08:00
原封不动的把一篇文章看完了,耗时 10 分钟。
|
9
mringg 2022-08-29 09:13:02 +08:00
警察已经开始摆烂了
|
10
qrobot 2022-08-29 09:14:21 +08:00 8
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 就好了 所谓的 `特殊分隔符`简直是最愚蠢的做法, 难道我的报文中就不能出现对应的特殊符号吗? `固定消息长度` 简直是浪费内存和网络开销。完全不可取。 因为是流协议, 所以需要应用自己去判断写入的字节什么时候已经达到的末端。 |
11
tairan2006 2022-08-29 09:15:21 +08:00
其实这块儿的中文术语很模糊,报文、帧、数据包啥的,用英文表达会好一点。
有的书把 packet 翻译成报文,有的把 message 翻译成报文,服了… |
12
yyf1234 2022-08-29 09:15:41 +08:00 via iPhone 1
|
13
eason1874 2022-08-29 09:15:51 +08:00 4
热帖预订。顺便提示楼主,还有一个流量密码:HTTP 状态码一律 200 、HTTP 请求方式一律 GET/POST
|
14
TomVista 2022-08-29 09:15:53 +08:00
无所谓了,只要你能听明白, 需要一个上层协议来拆分信息就行
前一阵子有个沙雕,非要我发送的时候,给他拆好 .dog 我接收的怎么是这样子 .jpg 你那里有问题 .jpg 不是我的问题 .jpg 不是我负责的 .jpg 你前端改改 .jpg |
15
darkengine 2022-08-29 09:21:49 +08:00 1
TCP: 我把东西按顺序给到你了,我们也不知道你们发的啥玩意儿,自己看吧
|
16
qrobot 2022-08-29 09:22:07 +08:00
当我看到 TCP 粘包的时候,我很震惊, 后面我开始解释 TCP 没有粘包, 只有 “因为是流协议, 所以需要应用自己去判断写入的字节什么时候已经达到的末端。” 后来我渐渐的麻木......
|
17
mercury233 2022-08-29 09:22:19 +08:00
TCP 粘包就是理论上不存在但实际上必须处理的东西 /狗头
|
18
Rache1 2022-08-29 09:22:51 +08:00 2
|
20
miyuki 2022-08-29 09:23:57 +08:00 via iPhone
packet frame message
跨频道聊天是吧 |
21
nothingistrue 2022-08-29 09:24:07 +08:00
四层传输层 TCP 协议流式,七层应用层通过缓冲区映射成数据包处理,说粘包并没错。但是“粘包”这个词是生造的,用于新手快速理解还可以,再深入点就该换成“分帧取帧”,或者“帧解码”。
|
22
qrobot 2022-08-29 09:36:44 +08:00
@nothingistrue #21 你确定你理解的是楼主所说的问题, TCP 帧在应用层是不关心的。 而所谓的 “判断写入的字节什么时候已经达到的末端” 是需要自己解析的
而且你说的 “分帧取帧”,或者“帧解码”。 是指什么? 说的是 解析 RFC 793 里面的 `TCP Header Format` 吗? 很抱歉,在用户使用协议上,没有权限读取对应的 `TCP Header Format` , 要么使用 tun/tap 等虚拟网卡, 要么使用 pcap/winpcap/npcap 或则 win10 的驱动网络拦截。 但是这些 TCP 协议的操作,往往都不是 TCP 使用用户来进行操作的, 楼主很明显是在使用 TCP 协议, 而不是解析 TCP 协议 |
24
tool2d 2022-08-29 09:44:33 +08:00
HTTP1.0 好像就是根据 connection:close ,来判断 HTML 是否已经完全传输完毕。
也不是所有的 TCP 都有 content-length 属性,在那个 IE 时代,经常遇见下载到一半的网页突然断开。 |
25
someonedeng 2022-08-29 09:45:15 +08:00
在 TCP 这层不用考虑这个
|
26
lysS 2022-08-29 09:46:53 +08:00
TCP 有所谓的“粘包”是使用情景出错了,你把两个以上的数据报放在一个 tcp 流里面传输了;正常的应该是一个“包”一个连接。像 HTTP 的长连接就是这种情况,不过 HTTP header 有 length 可以解决“粘包”
|
27
nothingistrue 2022-08-29 09:48:17 +08:00
@qrobot #22 网络通信是七层,不要死扣在传输层 TCP 协议这一个上。帧的英文是 Frame 。还有不要再回复了,这贴是给楼主的内容农场引流的,正方反方意见都不重要,都会给楼主引流。
|
28
reallynyn 2022-08-29 09:52:21 +08:00
他们说的 tcp 粘包,应该是指 nagle 算法吧。。
|
29
oneisall8955 2022-08-29 09:53:54 +08:00 via Android
|
30
exiledkingcc 2022-08-29 09:56:10 +08:00
TCP 没有包,但是这篇文章非要把指出这个事实的人扣一个“粘包警察”的帽子,似乎还有点得意。
基于错误的概念讨论一大堆东西都是没有意义的。 就这篇文章来说,TCP 的包是啥它自己清楚吗? 是你调用一次 socket write 的数据,还是 wireshark 抓包看到的一个 TCP 的条目?还是你应用层自己定义的逻辑结构? 概念都不定义清楚就自说自话,就是一堆废话。 |
31
TsubasaHanekaw 2022-08-29 09:58:47 +08:00
掘金在某些人看来已经是内容农场了么 哈哈哈
国内要啥社区生态啊 |
32
boywang004 2022-08-29 10:00:09 +08:00
就喜欢看这种话题,掐!打起来!别停手!
小马扎、花生米已经就位啦! |
33
qwerthhusn 2022-08-29 10:01:20 +08:00 1
奥山 YY 来人
|
34
hankai17 2022-08-29 10:05:14 +08:00
之前也看过很火的几个黏包警察的帖子
面试的时候也被问过 大概就是解决黏包的方案 比如 <content-length>[content] |
35
keepeye 2022-08-29 10:09:54 +08:00
其实说的不是报文粘包,而是消息解析的问题
|
36
tangchi695 2022-08-29 10:14:15 +08:00
我不管,我的 TCP 就是要粘包[手动狗头]
|
37
fkdtz 2022-08-29 10:27:24 +08:00
TCP 只保证可靠数据传输,没说把数据一个个拆开好给你,这件事应该由上层协议负责处理。
如果是这样的话,你也可以提出这样一系列问题: 如何解决 IP 协议不能可靠数据传输的问题?常规解决方案是用 TCP ; 如何解决 Ethernet 协议与全球服务节点连接问题?常规解决方案是使用 IP 协议; ... 回过头来看,这正是「分层」思想的奥义所在啊,每一层只处理好自己的事儿。 |
38
MrLin 2022-08-29 10:29:01 +08:00
·粘包·真是误人子弟,还有一大堆捧的,还在那里抠概念,错的就是错的
|
39
djoiwhud 2022-08-29 10:53:00 +08:00 via Android 1
|
40
byte10 2022-08-29 10:56:26 +08:00
@fkdtz 这解释到位,可以。
好几年前我一直认为 tcp 粘包是一个非常复杂的事情,一直没认真去看,后来要面试就专门去看 TCP 粘包。tmad 差点颠覆我的认知,这算个屁粘包,不知道哪个土鸡 提出来的。后来终于看到 V2 原来也有很多人不认可这个事情,那我就放心了,原来我的认知没错,某些人的问题。。。 |
41
0o0o0o0 2022-08-29 11:15:19 +08:00 2
生造词只会把问题弄得更复杂,明明很简单的原理,一句话就能说清楚的事情,非要生造一个词,然后再写一篇文章来解释这个词,把问题弄得更复杂。
还有,你说人家是“tcp 警察”,我觉得你是“tcp 恐怖分子” |
43
nekoneko 2022-08-29 11:26:23 +08:00
tcp 流式传输哪来的包, 脑袋里长了个包吗...
|
44
cweijan 2022-08-29 11:28:28 +08:00
@mercury233 这种情况也不能叫 tcp 粘包, 叫应用层粘包才对.
|
45
DonkeyBenjamin 2022-08-29 11:29:26 +08:00
这就是中文 cs 界的恶心之处,总是发明一些莫名奇怪的称呼。英文 tcp framing tcp stream 就很直观
|
46
bug123 2022-08-29 11:41:43 +08:00 1
十年前看网络编程书籍的时候有“tcp 粘包”的说法,其实是说需要一个业务协议去分包,比如:length + body 的格式,懂得都懂,每天没事做就拿出来喷一次,何必呢
|
47
zachgenius 2022-08-29 11:48:56 +08:00
粘包 难道不是“碰瓷”的意思? emmmm, 这个标题我都没看懂......TCP 警察......你再说某夫网?
|
48
icyalala 2022-08-29 11:53:29 +08:00
早上看到帖子乐了,以为大家会调侃一下粘包警察的耿
结果。。哈哈哈 |
49
moremoney 2022-08-29 11:54:26 +08:00 11
看到“TCP 粘包”这个专有名词,我表示极度震惊。连夜打车回到家里,战战兢兢翻开《计算机网络》,拿着放大镜仔细看了半夜,也没看到“粘包”两个字。我的后背不觉地渗出致密的汗水,双手止不住地发抖。匆忙打开电脑,一篇篇地翻着论文,试图寻找关于这个词的信息。可眼看天就要亮了,我依旧一无所获。我失望的躺在床上,满脑子都是“粘包,粘包,粘包!”,横竖睡不着,不得已打开了知乎,写下了一个问题“究竟什么是 TCP 粘包”。不一会儿答案就如雪花儿般涌了出来,每一片雪花上都写着一句话“TCP 没有粘包”。我颤抖的双手终于停了下来,一股热流从我心底涌到泪腺。啊,原来我并不孤独。
|
50
agagega 2022-08-29 11:57:45 +08:00 via iPhone 1
讨论一个东西的前提是得有定义,谁来定义这个 TCP 的包概念?其次,同样是流式读写,没有人会在读写文件的时候说有粘包问题吧?
|
51
DamonLe 2022-08-29 11:58:47 +08:00
哈哈哈哈,每年都有几次粘豆包。[头秃]
|
52
julyclyde 2022-08-29 13:14:54 +08:00
建议粘豆包用户都改用 websocket
|
53
NullData 2022-08-29 13:50:57 +08:00
@TsubasaHanekaw 掘金已经和内容农村差不多烂了
|
54
xilou31 2022-08-29 14:18:29 +08:00
某种意义来说,楼主已经成功了,确实吵起来了 (doge
|
55
leexy 2022-08-29 14:30:34 +08:00
|
56
ipwx 2022-08-29 14:34:21 +08:00
TCP 确实有“粘包”问题。
所以为什么要死磕 TCP ?找个 TCP 上层的、有“消息”概念的协议不好嘛?比如 WebSocket ? 我有些反感粘包警察,是因为早就被标准化解决了无数遍,直接拿来就能用(比如 WebSocket 这个五层协议)的问题,非要当做现实中一个重大问题去翻来覆去地讨论。 |
57
nekoneko 2022-08-29 14:36:57 +08:00 1
分包组包这是网络层干的事情, 跟传输层有什么关系.
看 ip 协议有个分包组包, 然后造个 tcp 的拆包黏包, 真的是恶心啊, 很容易把基础不行的人带歪. |
59
fuge 2022-08-29 14:41:32 +08:00
nnmlgbb
|
61
fan123199 2022-08-29 15:17:18 +08:00
搜了下,OP 文章提的都是网络上很多年就有的名词和争议, 怎么都在骂楼主扣帽子。。
|
62
Rache1 2022-08-29 15:25:58 +08:00
@TsubasaHanekaw 不是看起来是,而是他已经在朝这方面做,用 Google 搜一下 site:juejin.cn inurl:/s/ 你就能体验到了
|
63
ipwx 2022-08-29 15:33:07 +08:00
@ChoateYao 嗯我确实说错了,在通用模型里面属于第四层应用层。HTTP 和 WebSocket 都属于应用层。
另外如果看 HTTP 和 WebSocket 的关系,实际上 WebSocket 可以独立于传统的 HTTP 服务器单独使用,只不过 Handshake 这一步好像用了 HTTP header 。但如果一整个端口都用于 WebSocket 应用程序的话,其实可以忽略 HTTP 协议这玩意儿。 WebSocket 单独使用,你可以参考币的交易所协议。 |
64
ipwx 2022-08-29 15:34:46 +08:00
@nekoneko 吗吗,你的言论有些“反粘包警察”哦。
所以其实我“粘包”打引号了。虽然 TCP 确实不存在粘包这个概念,但是在应用中这个“问题”确实存在。我是不关心这玩意儿到底用“粘包”这个术语,还是准确地“因为 TCP 是流式协议所以必须自己处理数据包分割的问题”这么长的文本描述。在我看来,入乡随俗,如果“粘包”接受度广,用“粘包”来代指上面这句话我没意见。 |
65
julyclyde 2022-08-29 15:41:07 +08:00
@tool2d http 1.0 是靠 tcp connection close 来识别的; 1.1 才有 content-length 和 transfer-encoding chunked 这两个功能
|
66
llwwbb7 2022-08-29 15:41:20 +08:00
@TWorldIsNButThis 谷歌翻译给这个字的音标是 /Zhān/,点发音念的是 nian ,笑死了
|
67
nekoneko 2022-08-29 15:42:34 +08:00
@ipwx #64 所以如果叫 基于 tcp 传输的应用层消息拆分 我是没意见的, 非要叫个 tcp 拆包, 纯属误人子弟
|
69
UIXX 2022-08-29 15:51:52 +08:00
“你们不要再打了啦”
|
70
qrobot 2022-08-29 16:18:02 +08:00 1
@ipwx #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 协议的不理解,想当然的一个词语。 这种本身就应该抵制。"需要自己判断写入的字节什么时候已经达到的末端", 这就很好的解释了这个问题。 @ipwx 我没猜错你对 TCP 协议估计也是一知半解 。你写一次 tun 设备的 三次握手和四次挥手, 你就知道所谓的封包 /拆包 /重传 等等, 都已经做好, 数据已经有序的给你了。 你只要操作 Stream 就可以了。 我在跟你明确一下, 他说的粘包,指的是 代码中 write 两次, 另一端 read 一次的时候就可以读出来。 @ipwx 或则我这么问你, 如果你发现 TCP 有所谓的粘包, 请截图用 wireshark 抓包并且保存截图让我看看, 你能截屏出来, 我给你奖励 1w |
71
guang19 2022-08-29 16:26:17 +08:00
把协议设计好基本不会出现所谓的“粘包”
|
74
skies457 2022-08-29 16:56:28 +08:00 via iPhone
|
75
lizytalk 2022-08-29 16:59:11 +08:00
所谓“粘包问题”不就是设计一个应用层协议的问题么?在 TCP 协议(传输层)的范畴中,问题不存在就不是不存在...
|
76
ipwx 2022-08-29 17:04:48 +08:00 1
@qrobot 我不否认粘包实际不存在。我知道 TCP/IP 。但我觉得既然这么多人叫,那在别人都这么叫的语境下,借用这个术语表达他们的意思,我没意见。。。
为啥要这么纠结术语的纯洁性。DL 论文里面一堆(数学)术语乱用,只要该 domain 认同,不也就这么过来了。 |
77
sky857412 2022-08-29 17:28:19 +08:00
不知道在吵吵啥,听得懂就行,非 BB 半天你这概念不对,描述不对
|
80
e7 2022-08-30 09:34:04 +08:00
别纠结“粘包”这个词翻译对不对,令我震惊的是大多数人好像都不知道这回事
|
82
tabris17 2022-08-30 15:00:06 +08:00
TCP 粘包,UDP 汤包,ICMP 叉烧包
|
83
vishun 2022-08-30 16:42:31 +08:00
那 tcp 没有粘包,upd 也没有粘包,粘包这个词是怎么来的?😵
|
84
qrobot 2022-08-31 10:24:28 +08:00
@skies457 #74L
我从未听过 http 协议中用 \n\n 来最为判断文本已经达到的末端。 根据 http 协议 `content-length` 用来判断数据大小是多少, 即使在早期也是 一次请求,一次响应, 用 tcp connection close 来识别的。 请问你说 的 \n\n 是哪个版本? |
85
0o0o0o0 2022-08-31 10:52:35 +08:00
@vishun #83
说白了就是没有了解 tcp 的原理,没有了解流的概念,导致了 “发送两次,却一次就能全接收了”。 也就是 “我明明辛辛苦苦把数据分成两次(“他认为这是两个包”)发送,怎么一次就全接收了,肯定是 tcp 协议把我的两个 ‘包’ 粘在一起了” ,所以有了 “tcp 粘包” 这个概念。但是对于 tcp 来说是没有包的这个概念的,是发明 “粘包” 的这个人没有了解 tcp 原理导致的。 同理,如果一个人只知道流,没有包的概念,那他遇见 udp 就会产生“udp 拆包”,tcp 是保证顺序的,udp 不保证,他还会产生“udp 乱流”的概念,因为不知道一个东西怎么用就强行用会导致无数个“xx 问题”的概念,但是这些概念本身没有什么意义,因为如果一开始就了解一下什么是流,“粘包”这个概念根本就不会产生。 |
86
skies457 2022-08-31 11:02:28 +08:00
@qrobot 楼上有人纠正过了,是\r\n\r\n.... 这个分隔符用来分割 http header 的 content 的
|
87
Joker123456789 2022-08-31 15:27:21 +08:00
一个个都在 纠正 TCP 没有粘包, 我看了就头疼,为什么你们接受不了这个形容词呢? 如果你们要纠正,那就请你拿出正确的形容词出来(必须是业内认可,通用的,不能是自己造的)。
无论你们认不认,有一个事实 已经是既定的了, 那就是听到 TCP 粘包,大家就知道 是接收端 读到了数据,但是数据里 不止一条消息,需要自己去拆分出来。 粘包这个形容词 已经是业内通用了的, 你们非要来纠正,但是又拿不出真正通用的 形容词。 恕我直言,这种行为叫抬杠。 |
88
julyclyde 2022-08-31 15:53:07 +08:00
@Joker123456789 正确的叫法是“一种对协议进行错误解析的方式”
|
89
xsen 2022-08-31 19:22:43 +08:00
这个一开始是从 binary protocol 那边过来的,不过那边不叫粘包
叫 message parser 或者 message pack 简单来说就叫组包、拆包,这本身就是属于 protocol 层面的问题 N 年前某一天,突然听到粘包这个词——找了老半天还是没反应过来 |