怎么理解 TCP 粘包与拆包?

2021-01-23 18:40:22 +08:00
 narutow

记得一个大佬跟我说过, "TCP 哪有什么粘包拆包的问题, 人家本来就是流式协议, 你用它传你的结构化数据, 你是做数据的序列化和反序列化, 而不是在克服 TCP 的缺点."

这样的理解是否准确呢, 大家什么看法. 本菜鸡感到疑惑~

11818 次点击
所在节点    问与答
99 条回复
Jirajine
2021-01-23 21:15:18 +08:00
@l00t #19 是根本就不存在这种所谓的“现象”,你读写文件、打 log 的时候怎么没遇到过“粘包”?
说到底还是没把 tcp 当流看待。
opengps
2021-01-23 21:24:54 +08:00
说话说太快了,没带标点,就是粘包
cs419
2021-01-23 21:31:41 +08:00
粘包是 tcp 编程 的雾里看花
你想了解 tcp 编程 却没实际经验的 产生了错误的认知

建议通过一个实际场景去学习
尝试写个远程调用 或者跨语言调用 的例子
写出来 你就不会再想粘包的概念了
seanxx
2021-01-23 21:41:21 +08:00
满贴嘲讽,鄙夷.....
太臭了这氛围
reedthink
2021-01-23 21:49:08 +08:00
TCP 详解没看完吧,附一句原文:“两个应用程序通过 TCP 连接交换 8bit 字节构成的字节流。”
ps:创造粘包概念的人,似乎对 TCP 有点误解
Immortal
2021-01-23 21:50:04 +08:00
@seanxx #24
这贴反而是我见过认真科普数最多的粘包贴
yolee599
2021-01-23 21:56:50 +08:00
对,我就是粘包警察! TCP 不存在粘包说法! TCP 不存在粘包说法! TCP 不存在粘包说法!
nicebird
2021-01-23 22:11:35 +08:00
主要是某些人把粘包当成一个问题,然后写文章解决。实际上粘包只是基于 tcp 设计发消息的表现,只要正确理解 tcp 是流式的就明白了一定会有所谓的粘包现象。
当然实践上也能写出一些不拆包直接收,直接强转就能用的情况。那是因为消息发的太慢、包太小,刚好 tcp 放在一个 ip 包里发了出去,收到后刚好是一个完整的包罢了。
Jaron0608
2021-01-23 22:28:23 +08:00
TCP 是一个面向字节流的协议,它的任务就是在提供流量控制、拥塞控制等特性的前提下,将 Payload 中的上层协议数据完成可靠的传输。

它并不关心 Payload 中的数据格式,这里所说的“包”的包实际上是上层应用层协议的 Header+body,并不是 TCP 数据包。

定义应用层协议时,一般需要满足下面三种需求之一:

- 固定协议包长度(可拓展性低)
- 指定协议包终结符,例如 redis 的 RECP 协议
- 指定一个 Length 字段,表明协议包长度,例如 HTTP 协议

根据这三个需求,在处理 TCP 流时找到应用层协议包的分界,就能拆解出一个个单独的应用层包。
Cbdy
2021-01-23 22:31:12 +08:00
粘包警察不请自来
Meltdown
2021-01-23 22:40:27 +08:00
本来就是这样啊,如果有往文件里读写结构化数据和知道 tcp 读写时读到或写入的长度不一定是指定的长度就自然而然考虑到这个问题了。这个粘包都快成专业名词了,我看 brpc 的文档里都这么说了。。。
xuanbg
2021-01-23 23:00:10 +08:00
TCP 设计出来就不是直接给应用程序用的。应用程序应该使用应用层协议来使用 TCP,譬如 http 。
chenqh
2021-01-23 23:07:58 +08:00
TCP 是流,但是应该算是车流吧,不是水流
chenqh
2021-01-23 23:11:34 +08:00
@Jaron0608 我到觉得 HTTP 主要是一个链接只发一个请求,导致粘包情况比较少
love
2021-01-23 23:23:05 +08:00
我滴妈这都 2021 年了,怎么还在说这么无聊的问题,TCP 是字节流哪来的粘包拆包,你们能不能发个代码片段让我见识下
1109599636
2021-01-23 23:29:11 +08:00
@Jaron0608 这个回答很不错,大部分回复毫无帮助甚至营养可言,即使是 v2 讨论起问题脾气也是大,网络环境不乐观啊。。。
micean
2021-01-23 23:35:19 +08:00
因为数据到缓冲区,发不发是网卡驱动决定的,可能马上发,也可能等一会发,缓冲区满了就分几次发
lizytalk
2021-01-23 23:36:56 +08:00
粘包本来就是伪问题。想用一个包一个包的模式就自己搞一个应用层协议,或者用现成的啊。tcp 本来就是流传输的协议,非要让人家传输包,tcp 也很无奈啊
micean
2021-01-23 23:47:56 +08:00
比方说,缓冲区大小是 1024,你每秒发个 10byte 的帧,对方哪需要处理什么所谓粘包拆包的问题,但是你要发个 10kb 的帧,那这一帧肯定是拆开发送的啊
neoblackcap
2021-01-23 23:57:44 +08:00
原理就不讲了,我说说历史吧
socket 这套东西呢,其实本质上是历史物理过程的模拟。TCP 就是模拟电话而出现的,UDP 就是模拟电报。
我们当然可以说拍了“一个电报”给别人,而且说明一件事情的时候,我们往往可能要用到“多个电报”。
然而当用电话的时候则不同,我们也可以说打了“一个电话”给别人,然而往往说明一件事情的时候,我们用“一个电话”就可以搞定了。
为啥打电话的时候不会出现“粘包”而 socket 编程又会出现“粘包”呢?当大家回忆自己是怎么打电话的时候,大概就明白了为啥不“粘包”了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/747735

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX