Socket 分包的原因及解决办法

Socket 粘包分包的原因及解决办法

该文章部分引用来自:https://blog.csdn.net/double2hao/article/details/83211334

原因

socket发生粘包分包实际上是在TCP传输协议对数据的优化,TCP是“流”协议,传输的过程就像流水一样没有边界,没有界限,而实际上我们只需要取出我们发送的部分即可;这里说明下UDP是"数据包"协议,所以在UDP中不存在粘包分包的情况。

为什么会分包?

在传输过程中,TCP为了保护网络(也称为流量控制),并不是接收到什么就传递什么,而是根据一系列的限制决定发送多少数据出去,这些限制有:用户缓冲区(接收发送缓冲区)、TCP底层缓冲区(各系统下表现会不同)、MTU(最大传输单元,属于数据链路层)等等,想进一步探究参考:

  1. https://www.cnblogs.com/silyvin/p/11996349.html
  2. https://www.zhihu.com/question/48454744

概念

粘包:
当发送的字节数据包比较小且频繁发送时,Socket内部会将字节数据进行粘包处理,既将频繁发送的小字节数据打包成 一个整包进行发送,降低内存的消耗。
分包:
当发送的字节数据包比较大时,Socket内部会将发送的字节数据进行分包处理,降低内存和性能的消耗。

例子解释

当前发送方发送了两个包,两个包的内容如下:
123456789
ABCDEFGH

我们希望接收方的情况是:收到两个包,第一个包为:123456789,第二个包为:ABCDEFGH。但是在粘包和分包出现的情况就达不到预期情况。

粘包情况

两个包在很短的时间间隔内发送,比如在0.1秒内发送了这两个包,如果包长度足够的话,那么接收方只会接收到一个包,如下:

123456789ABCDEFGH

分包情况

假设包的长度最长设置为5字节(较极端的假设,一般长度设置为1000到1500之间),那么在没有粘包的情况下,接收方就会收到4个包,如下:

12345
6789
ABCDE
FGH

如何处理粘包分包?

在数据层面处理:

  1. 约定结束符,遇到结束符时分割数据。
  2. 发送数据时约定数据长度,获取数据时先接到长度,然后根据长度分割数据。
  3. 发送数据末尾拼接换行符,使用BufferedReaderrd.readLine(),原理同上。

技术选型:

  1. 使用成熟的socket框架,很多框架会帮忙处理合包的操作。
  2. 使用WebSocket,WebSocket是一个message-based的协议,它可以自动将数据分片,并且自动将分片的数据组装。
Socket分包和粘是在网络通信过程中常见的问题。当数据通过网络传输时,由于网络环境的不稳定性和数据传输的特性,会导致数据被拆分多个进行传输(分包)或多个数据被合并成一个进行传输(粘)。 分包问题主要是指发送方将一段数据拆分多个发送,接收方收到这些后需要重新组装成完整的数据。这可能导致接收方无法正确解析数据,出现错误或异常。 粘问题主要是指发送方将多个数据合并在一个中发送,接收方收到这些后需要将它们正确地分割成单独的数据。如果接收方无法正确处理这些数据分割,就会导致解析错误或异常。 为了解决这些问题,可以采取以下方法: 1. 头+体:在传输数据时,在每个的开头加上一个固定长度的头,用于表示该的长度。接收方先读取头,然后根据头中的长度信息读取相应长度的数据,从而正确地分割出每个数据。 2. 分隔符:在传输数据时,在每个数据的结尾加上一个特殊的分隔符,如换行符或其他不会在数据中出现的字符。接收方通过读取数据,并根据分隔符将数据正确地分割成单独的部分。 3. 固定长度:在传输数据时,固定每个的长度,无论数据是否填满该长度。接收方按照固定长度读取数据,并根据长度信息判断是否有多余的数据。 4. 使用消息协议:使用特定的消息协议,在每个消息的开头添加消息长度信息。接收方根据消息长度信息解析出每个完整的消息。 以上方法只是一些常见的解决方案,具体应根据实际情况选择合适的方法来解决分包问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值