1 unused 178 天前 via Android ![]() 出警! |
![]() | 2 MossFox 178 天前 ![]() 还在粘还在粘 有 http(s) 这种上层协议了就别担心粘了,帮你分好了的,闭着眼放心用。 |
![]() | 3 seers 178 天前 via Android http 已经在应用层了 |
![]() | 4 laikicka 178 天前 字节流怎么粘?? |
5 drymonfidelia OP @laikick 例如前一个包没发完又发出了下一个包 |
![]() | 7 laikicka 178 天前 @drymonfidelia 那不是你代码写的有问题吗? 建议去看看 recv 和 send 的函数 |
![]() | 8 momocraft 178 天前 楼主怎么当上 mod 的 介绍下经验 |
9 drymonfidelia OP @laikick 具体是什么问题?如果两个包长度过大的话确实有可能出现这种情况吧 |
10 drymonfidelia OP |
![]() | 11 sigma65535 178 天前 应用层才有包的概念,tcp 是字节流 |
![]() | 12 laikicka 178 天前 @drymonfidelia 做好分包啊. 不过为什么要自己实现一个 tcp 协议呢? |
13 neoblackcap 178 天前 http 协议已经是应用层协议了,nginx 会按照一个个 http 请求转发。nginx 的 http 协议解析属于教科书级别,基本上不用考虑人家会写错。 如果你需要长连接的,请去学习一下 TCP 编程。否则对 TCP 模型不了解,你还无脑上,那就是刻舟求剑。 |
![]() | 14 itechify PRO 通通抓起来 |
15 drymonfidelia OP @laikick 我就是不想自己实现,所以才问是不是套个 http/ws 就没有粘包问题了啊 |
![]() | 16 ragnaroks 178 天前 如果是想找个类 tcp 的东西拿来用,又不用考虑从中解析数据,那把 websocket 当 tcp 用是可以的,websocket 会确保每次 onMessage 都是一个完整的包 |
17 henix 178 天前 nginx? 应该用编程语言的库或框架吧,比如 java 的 netty 或 Python 的 twisted 推荐用 zeromq 的 request-reply 模式,把底层的 TCP 封装了 |
18 kingcanfish 178 天前 @unused 可恶啊 被你抢了一楼 |
19 LoNeZ 178 天前 有时间发帖, 不如直接问 AI ... 要不先把整个协议栈理解一遍? |
20 iseki 178 天前 via Android 他们的意思是没有“粘包”这个说法,你说的现象存在,但你不该将之视为一个问题。 |
21 jworg 178 天前 分好几种情况,你想问哪一种,HTTP 与 HTTP2 以及 sni proxy 与 static serve 做的似乎都不一样。如果是最简单的 HTTP + static serve 就是 \r\n 换行魔法呗。 |
22 roundgis 178 天前 via Android http 粘啥。 |
![]() | 23 jiangzm 178 天前 http 服务为什么要考虑 tcp 问题,也不用考虑长链接问题。 |
24 Keuin 178 天前 2025 年了还在粘包 |
25 xuwen 178 天前 按照协议规定读 tcp 数据,压根就不存在粘包的问题。http 服务本来就已经按照协议规定读包了,所以压根就不存在这种东西 |
![]() | 26 duzhuo 178 天前 感觉可以复习一下计网分层那里 HTTP 作为上层协议,无需关心网络传输细节,只需通过 TCP 接口发送/接收数据。 |
![]() | 27 xyooyx 178 天前 @drymonfidelia #10 建议把基础原理了解下,会高效不少 |
28 kitrap 178 天前 via Android ![]() 粘包这傻叉说法是从哪来的? |
29 kzfile 178 天前 我记得 2018 年论坛里就有粘包警察了 |
![]() | 30 wangtian2020 178 天前 ![]() 粘包从来不是问题,只是现象,一种符合通信协议的现象。 有些人非要自己不用库,自己去处理连接,那就自己处理这种情况 |
![]() | 31 zhangsanfeng2012 178 天前 粘包,你们读"zhan bao"还是"niao bao" |
![]() | 32 liu731 PRO 买了台发动机担心齿轮坏了是吧? |
![]() | 33 rrfeng 178 天前 via Android 最近被 mtu mss gso tso 折腾 粘包能不能粘高级点 |
![]() | 34 mmdsun 178 天前 还好这是 25 年,不然 OP 要被粘包警察喷死。 |
35 FishBear 178 天前 websocket http https 都是跑在 tcp 上的哦(除了新的 quic 在 udp 上) nginx 跑的 http https 也是在 tcp 上的哦 tcp 性能最高 封装一次就损耗一次性能. 粘包这个词不大好,应该是我们 csdn 博客创造出来的概念? tcp 只关心流,不关心你的数据,你应该己解数据流. |
![]() | 36 zwb9412 178 天前 好奇 OP 为啥有 MOD 权限? |
37 darklinden 178 天前 http 和 websocket 是在协议封包的,也就是说如果一个库实现了 http 或者 websocket ,当你使用这个库的时候,面对的接口就只有“包”为单位,不存在“粘” |
![]() | 38 cheng6563 178 天前 不自行建立 TCP 连接,那你是用 UDP 咯,UDP 那就你自己全得考虑了哦。 |
![]() | 39 sola97 178 天前 笑死,我上个月去面试一家小公司,面试题里就有问粘包是什么 |
40 cnuser002 178 天前 ![]() 楼主的担忧我能理解。比如一个发送端,一个接收端。 我当然希望每次接收端收到,都是一个完整的消息,不就能直接处理了么? 但如果这个消息,真的很大呢? 或许他一次发送不完,那我收到的就不全。我要等,这可就麻烦了呀。同样的,下一次把之前的尾巴,跟下个报文的头一起发送了,我还得拆,更麻烦了。 嗯。Tcp 它就有这种操作,这不是它的问题,而是它的设计,就是基于 Stream ,像流水一样一直给你灌数据。 底层打散但是保证消息还是前后有序进来的。对于这种流,需要按流的处理方法,收取后进入缓冲区,然后在缓冲区里,根据协议里面的约定,比如固定包头,特殊符号来解析出内容。 而这个就是 HTTP 干的事情。 所以你的需求,用 HTTP 就可以实现。你可以认为 HTTP 接口每次拿到的,就是完整的数据。 WebSocket 也可以。 |
41 deplives 178 天前 都 5202 年了,还搁这粘包呢? tcp 还在字节流层面,都没有所谓数据包的概念,搁这粘啥呢 |
![]() | 42 monkeyWie 178 天前 via Android 还在粘包,逮捕 |
43 strobber16 178 天前 v2ex 常态化整治粘包斗争成效显著 |
![]() | 44 mhycy 178 天前 暴论!半桶水 java 书籍害人不浅 |
![]() | 45 tangchi695 178 天前 TCP 警察出警! |
46 macaodoll 178 天前 抓起来抓起来 |
47 julyclyde 178 天前 ![]() 你只要别 亲自在 socket 上执行 read 、write 、recv 、send 基本上都没事 你只要 *面向 request 编程* 而不是 *面向 stream 编程* 就可以把 *从 stream 里截出 request* 这个工作外包给 library 需要强调的是: 正常人无法对 TCP 的 segment 进行处理,正常人只能看到 TCP 是一个 stream |
48 hayala 178 天前 这个帖子看着很欢乐 |
![]() | 49 Mystery0 178 天前 via Android @zhangsanfeng2012 读 nian bao |
![]() | 50 catamaran 178 天前 ![]() @Mystery0 虽然也念 nian bao ,但是应该是 zhan 包,包 zhan 在了一起,动词,指的是一种现象。nian 一般用作形容词,比如粘豆包。再比如:这个胶很 nian ,所以 zhan 的很结实。 |
51 maigebaoer 178 天前 via Android 抓起来! |
![]() | 52 yolee599 178 天前 via Android 说 TCP 粘包属于常识性错误,因为 TCP 协议就像一条水管,会源源不断的给你数据,它只负责把数据按先来后到的顺序交给你。 至于你需要一包一包的应用数据,那是应用层该干的事情,应用层需要给 TCP 数据一个边界标识,再通过这个边界标识来解析数据,如果还没检测到边界就暂存到自己开辟的缓冲区中,等检测到了边界就返回缓冲区里的数据,就够成了一个应用包。 |
![]() | 53 xuanbg 178 天前 应用层协议譬如 http 不就是用来给你封一个个包的嘛,既然封装好了包,就不会稀里糊涂粘在一起了,你大可以放心使用。至于 TCP 协议么,那是个数据流,并没有包的概念,所以也不存在粘不粘的。 再往下 IP 协议倒是分包的,就像一个个邮包,上面贴着收件人地址,路由器就是靠这个地址来转发数据包的。但路由器只管转发,并不管你包里面装的什么东西。 |
54 echoechoin 178 天前 @drymonfidelia #9 每个报文都需要一个头部,头部存放长度就行 |
56 iceheart 177 天前 via Android ![]() 整天粘包,吸管喝饮料,难道吸上来的是一块一块的? |
![]() | 57 ipwx 177 天前 楼主的需求是啥? 如果用 websocket 发送一个 message ,那它天然就是按 message 切分的,没问题。但是,message 有大小上限。如果你需要发送一个超过上限的 message ,你可能需要自己模拟一遍 “拆包”-“组装” 过程,相当于你用 websocket 消息流模拟了 tcp 的无消息流。 如果你想要在读取 post body 的时候期待客户端是一个一个数据包发送的,那不好意思,中间任何一个代理服务器甚至是路由器都可以修改数据包的形式,是可以任意重新组装重新切分的。 |
58 xiaomushen 177 天前 受不了,这都粘了 30 多年了吧? |
59 liuguang 177 天前 根本不存在粘包,粘包都是源于读取方法。 |
![]() | 60 masterclock 177 天前 2025 年了,还能出现 tcp 粘包 这词,我是没想到的 |
61 franswish 177 天前 很久很久以前还是学生的时候,搞嵌入式设备测试,用串口做上下位机通信,每帧报文几十字节不等,数据周期性发送,间隔固定且可调(从几百毫秒到数秒),简单做一个定时接收逻辑即可满足需求,不需要再做应用层根据帧头帧尾校验分帧。 后来用以太网口,走 TCP 协议做差不多的事,但是数据量大了很多,通信也变成非周期性且短间隔的了。还按原来串口的思维去理解 TCP ,发现完全搞不定,然后才领悟了为什么数据要有帧头帧尾校验,TCP 只负责收发数据的可靠性和连续性,要用数据得应用层自己去解。 结合我自己经历,我觉得喜欢说“粘包”的怕不是像我以前认知串口的一样,发一次就是一帧所以通过调整接收逻辑能一次收到完整一帧就不用在接收端先分帧再解帧了。 |
62 kneo 177 天前 via Android 正经回答下,不用。 |
![]() | 63 ipwx 177 天前 @franswish 不知道怎么搞定协议解析、切分消息(俗称解决粘包) = 我高中玩编程的水平。 那时候是真觉得这玩意儿也忒复杂了,怎么这么难搞。 现在嘛,不就是把 TcpConn 放到一个 Stream 里面,然后 string readNextChunk(int size) { int nLeft = size; string ret; char buffer[8192]; while (nLeft > 0) { int nRead = read(conn, buffer, min(nLeft, sizeof(buffer)); if (nRead == 0) { break; // EOF } for (int i=0; i<nRead; ++i) { ret.push_back(buffer[i]); } nLeft -= nRead; } return ret; } 其实第一个认知更新,是在网络条件下,read(..., 8192) 不一定能给你真的读出来 8192 bytes ,你得用循环读。然后这部分写成一个通用函数(比如上面这个 readNextChunk) 就行了。用的时候 int nextMsgLength = fromLittleEndianUint32Bytes(readNextChunk(4)); string msg = readNextChunk(nextMsgLength) |
64 zxjxzj9 177 天前 http 都已经包了一层应用层了你怎么粘。只有自己读 tcp 字节流,把字节流拆成了一小段之后读,读不干净才会粘啊! |
![]() | 65 codingmiao 177 天前 粘包警察是什么梗,自己 netty 写个通信,还是要考虑粘包半包的嘛 |
66 csfreshman 177 天前 在 v2 ,关键字"粘包"自带流量……… |
![]() | 68 qbmiller 171 天前 感谢 dubbo ,让我学习了一次粘包。2.6.x 版本的 thrift 协议。 |