Socket 粘包和分包问题

概念

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

例子解释

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

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

粘包情况

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

123456789ABCDEFGH

分包情况

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

12345
6789
ABCDE
FGH

处理方式

因为存在粘包和分包的情况,所以接收方需要对接收的数据进行一定的处理,主要解决的问题有两个:

  1. 在粘包产生时,要可以在同一个包内获取出多个包的内容。
  2. 在分包产生时,要保留上一个包的部分内容,与下一个包的部分内容组合。

目前处理方式主要两种:

一、给数据包的头尾加上标记。

比如在数据包的头部加上“START”字符串,尾部加上"END"字符串,这样可以解析出START和END之间的字符串就是接收方需要接收的内容。(当然真正处理的时候不可能使用START和END这种混效率较高的字符串,此处只是个例子)
上边两个包的例子就可以如下:

START123456789END
STARTABCDEFGHEND

二、在数据包头部加上内容的长度

发送方在发送的时候就可以在包头加上包的长度,接收方每次接收的时候都根据头部的长度去获取后面的内容。
上边两个包的例子就可以如下:

PACKAGELENGTH:0009123456789
PACKAGELENGTH:0008ABCDEFGH

处理例子

头尾标记处理

粘包

START123456789ENDSTARTABCDEFGHEND

获取第一个START和第一个END的位置,然后获取他们之间的内容,第二个包的内容就是获取第二个START和第二个END的位置。

分包

START1234567
89END

每个包要判断最后是否是END结尾,如果没有找到END,那么就保留上一个包START之后的内容,与下一个包第一个END之前的内容组合。

头部长度处理

粘包

PACKAGELENGTH:0009123456789PACKAGELENGTH:0008ABCDEFGH

获取“PACKAGELENGTH:”这个字符串后面4个字符,转化为数字就是包的长度,根据包的长度获取后面的内容,第二个内容的长度就是获取第二个“PACKAGELENGTH:”字符串后面的4个字符。

分包

PACKAGELENGTH:0009123456
789

获取“PACKAGELENGTH:”这个字符串后面4个字符,转化为数字就是包的长度,如果包结尾还没有获取完,那么就要获取下一个包前面的部分内容。

部分细节情况

看了前面的例子,比较善于思考的读者肯定已经想到了一些其他问题,这些问题处理起来方式和上面相似,笔者在此罗列一下,就不重复解释了,相信聪明的读者能够自己解决:

1、粘包和分包问题一起出现

START123456789ENDSTARTAB
CDEFGHEND

2、头尾标志由于分包获取不完整

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值