socket 编程中的粘包问题
关于粘包,查了一些资料,还是不太清楚。
我的理解是,A 与 B 的连接建立后,socket 将 tcp 字节流中的非数据字段进行拆解,并将数据部分放入该连接的输入缓冲区。当有多个 A->B 的包发来、且 B 没有对每一条数据及时进行处理时,多条信息就会同时存在于输入缓冲区中,首尾相连。如果数据部分没有分隔符或能够标识数据长度的字段,则很有可能出现无法分割出单条数据边界的情况,从而导致「粘包」。
如果确实会出现「粘包」现象,则解决方法是不是应该是:
- 确保接收方会及时处理发送来的数据,使输入缓冲区中同时只会存在一条发送来的数据;
- 保证发送端的数据中有分隔符或能够标识其长度的字段( 如 HTTP 消息 )。
不知道以上的理解是不是有误?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
理解的没啥问题,解决方案建议
不要
依赖于发送的数据一定能够被立即处理,而是从下面的角度出发:首先,需要明确什么是tcp中的粘包问题(具体可wiki),我这里大致描述下:
tcp粘包就是指在tcp的网络编程(当然不止tcp,其他粘包也差不多意思)中,由于tcp是流式的,tcp提供给应用层的接口,无法获知发送端一次发了多少数据,也没办法获知发送端发了多少数据,就造成下一次数据头紧跟着上上一次数据尾,直接提供给应用层,应用层无法感知何处是发送端一次发送的边界。
下面说一下tcp粘包具体的原因:是发送端tcp层可能会对数据封装成多个tcp段,不仅如此,还会对应用层的多次数据组成一个包,比如应用层第一次写'A',第二次写'B',第三次写'C',在Tcp层很可能是发送一个tcp段,包含的数据是'ABC',所以,这样不管是接收端是否一次读一个tcp段,都无法分辨出哪里是发送端应用层边界,俗称"粘包"。
好,下面就简单说一下楼主(主要的错误也就1点):
图片描述
如我上面所说,接收端以如何的方式处理都不是粘包的根本原因,因此,接收端一次读一个tcp段也是会造成粘包现象,从而到处严重的错误。
那么如何解决粘包:
被采纳的答案的两条建议都是正确的,不过第一条容易让人引起误会,以为tcp可以一次读出定长的数据。
没什么好办法,就是应用层自己设置协议解决粘包问题,最典型的就是采用协议头部和数据的方式。注意的是,这里应该用状态机实现接收端的功能,因为你不能确定发送端发了完整的头部,你就一定能收到完整的头部。
最简单的办法就是设置8个字节的头部,表示数据长度,接着就是数据。
那么发送端先发送8个字节的一个数字,表示接下来的数据大小是多少,接着将数据全部发送过去。接收端一直接受数据,一直等到接受满了8个数据,取出来,计算出大小(假设为n),接着继续读取n个字节,就是完整的一个应用层的包了。