socket 编程中的粘包问题

发布于 2022-09-06 10:15:26 字数 381 浏览 11 评论 0

关于粘包,查了一些资料,还是不太清楚。

我的理解是,A 与 B 的连接建立后,socket 将 tcp 字节流中的非数据字段进行拆解,并将数据部分放入该连接的输入缓冲区。当有多个 A->B 的包发来、且 B 没有对每一条数据及时进行处理时,多条信息就会同时存在于输入缓冲区中,首尾相连。如果数据部分没有分隔符或能够标识数据长度的字段,则很有可能出现无法分割出单条数据边界的情况,从而导致「粘包」。

如果确实会出现「粘包」现象,则解决方法是不是应该是:

  1. 确保接收方会及时处理发送来的数据,使输入缓冲区中同时只会存在一条发送来的数据;
  2. 保证发送端的数据中有分隔符或能够标识其长度的字段( 如 HTTP 消息 )。

不知道以上的理解是不是有误?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

念﹏祤嫣 2022-09-13 10:15:26

理解的没啥问题,解决方案建议不要依赖于发送的数据一定能够被立即处理,而是从下面的角度出发:

  1. 比如只发送定包长数据,接收端判断长度即可。或者在包头中加入当前包的长度信息
  2. 添加边际分割字符串(但是要注意文本中本身可能包含的可能性)
疯狂的代价 2022-09-13 10:15:26

首先,需要明确什么是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个字节,就是完整的一个应用层的包了。

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文