怎么理解 TCP 粘包与拆包?

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

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

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

11818 次点击
所在节点    问与答
99 条回复
VersionD
2021-01-24 00:06:01 +08:00
@opengps hh,很精髓,比起粘包警察的解释好多了
germain
2021-01-24 00:20:34 +08:00
用私有协议+编码+缓冲
aaronlam
2021-01-24 00:31:07 +08:00
b00tyhunt3r
2021-01-24 00:45:05 +08:00
@carlclone 讲两句呗
oisadfo
2021-01-24 01:14:12 +08:00
居然没有人来给粘包下个定义,都是各说各的
no1xsyzy
2021-01-24 02:17:56 +08:00
@lewis89 话说也有 SCTP 这种保序又分包的,但没什么人用的样子
后来的要么干脆 WebSocket 了
no1xsyzy
2021-01-24 02:30:16 +08:00
@seanxx @1109599636 是什么让你们有了技术工作者和爱好者会友善的错觉?
从新闻组时代开始就会花式嘲讽了好么:
https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/master/README-zh_CN.md
(原作者是 ESR, “开源” 一词的创造者)
iszengmh
2021-01-24 03:50:12 +08:00
其实你们只是想说粘包和拆包
iszengmh
2021-01-24 03:50:42 +08:00
其实你们只是想说 TCP
yayoi
2021-01-24 03:52:04 +08:00
websocket,http 和 tcp,stcp 不是一层的东西吧,所谓粘包是因为直接用了 tcp 却不实现应用层协议造成的问题,直接原因是不知道 tcp 的工作方式,根本原因是不了解通信的七层模型
iszengmh
2021-01-24 04:02:49 +08:00
其实你们只是想说 TCP 根本没有拆包和粘包,它们是应用层做的事情,应用层把数据拆成一段一段(拆包),在传输层利用 TCP 协议一段一段发送,接收数据的应用层又把一段一段数据组合起来成为一个完整数据(粘包),整个过程在应用看起来就只是发送了一次请求而已。
mengzhuo
2021-01-24 04:50:48 +08:00
不解释了

我原来是粘包警察

现在是面试别人的时候,故意挖坑,谁掉进去就直接不通过( ̄∇ ̄)
littlecreek
2021-01-24 05:04:11 +08:00
请教"粘包与拆包" 这俩对应的英文名词是什么? 我去学习一下.
ryd994
2021-01-24 06:02:23 +08:00
因为这帮人还不知道 sctp,既提供可靠性,也提供字节边界。
如果怕中间的设备不支持的话,还有基于 TCP 或 UDP 的用户态 sctp 库。

如果只是为了传输数据,谁没事手撸 TCP 啊,protobuf 不香吗?
lewis89
2021-01-24 06:20:55 +08:00
@no1xsyzy #46 关键是 99%的人 IP 以上的东西 就只听说过 TCP UDP,而且大部分路由器也只针对这两个做了 NAT 优化,搞不好你用其它的(我不是很了解 STCP ),就不兼容了... 好多路由器连 ICMP 都是默认防火墙拦了,而且从私有网到广域网上 层层 NAT,raw IP 协议根本行不通..
crclz
2021-01-24 09:02:01 +08:00
TCP 是面向字节流的协议。TCP 只负责传输字节序列。至于为什么 API (接收和发送)是以 byte[]为单位,只是因为批量处理数据的效率原因。TCP 代码里面并不对你发送的 byte[]做出分界,假设你要传输某 buffer[0:200],那么①传输 buffer[0:50]、buffer[50:200]和②buffer[0:100]、buffer[100:200],TCP 认为①②并没有区别。

这个字节流可以理解为 C#中的 Stream 或者 IEnumerable<byte>这两个编程接口。

TCP 的粘包是因为,本身就没有包的概念。你取到的字节数组有概率和传输的字节数组的“窗口”相同,给了你“包”的错觉,只是因为运气好罢了(从 IP 层的缓冲取走数据及时,并且中间的链路畅通)。
Orenoid
2021-01-24 09:49:32 +08:00
本质上就是在讨论如何在 TCP 流式数据里拆分出应用层的数据包,说到底就是个叫法问题,“粘包”还是“拆包”,但麻烦请用后者,错的就是错的。
也许你是能理解问题的本质,但你能保证你在传播“粘包”这个概念的时候,也保证听众不会错误理解吗?这个词传得越广,就越有可能导致很多新手以为 TCP 传输过程就是按照一个一个包去发送的。
nl101531
2021-01-24 10:12:02 +08:00
从一次协议请求来看,TCP 会将应用层数据分段后,转交给 ip 成,ip 成再次分片,当网卡收到数据后,ip 成会合并数据,然后转交给 TCP 成,TCP 是直接将这个段给到应用层,问题是这个段由于连接复用可能会包含多个业务请求含义。

个人认为,粘包说法很形象,没必要揪着流式协议这一点不放。
love
2021-01-24 10:40:34 +08:00
@nl101531 你说的是啥你理解吗,什么叫由于连接复用可能会包含多个业务请求含义?字节流由于效率因素才在接口层面允许一次读写多个字节本质上还是一个字节一个字节发送读取数据的字节流,一个字节流有什么粘包?这词还不是误解 TCP 而来的?
Mutoo
2021-01-24 11:44:39 +08:00
@littlecreek TCP message framing

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

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

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

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

© 2021 V2EX