消息处理
601字约2分钟
2024-12-12
消息推送采用的是流式传输数据的,避免不了要分块的问题(粘包/拆包),有几种方式来处理这类问题。
1. 固定块大小
即每个块的大小都是固定的,例如 1024 字节。每次收取到1024 字节,就认为一个完整的数据包,然后处理。不过这种方式灵活性较差,若果数据包小于指定大小,对剩余信息就需要进行填充处理;如果数据包大于指定大小,又得进行分包分片。
2. 以指定字符串为结束符
就是在数据包中添加一个结束符,例如 \r\n
,这样当收到数据包中包含该结束符时,就认为一个完整的数据包,然后处理。但在这种方式中,如果数据包中包含结束符,就需要进行其他的处理。
转义
比如在数据包中包含 \r\n
,但是数据包中又包含 \r\n
,这样在处理时会导致数据包被截断,所以需要将 \r\n
转义为其他字符,例如 \x01\x02
。当接收数据时,如果遇到转义字符,就替换为原始字符。但如果数据包体中包含\x01\x02
,又需要进行转义处理,重复此方法,所以使用这种方式尽量选用不常用的字符作为结束符,避免这种情况。这种方式不能很好的做到让用户任意输入,所以可以根据实际需求来选择。
转码
将数据包进行转码,比如转为 base64
然后利用 [END]
等字符来作为结束符,由于 base64
编码后,没有 [END]
字符,所以不会由于数据内容而截断数据包。这种方式可以使得用户随意输入,但需要注意的是,转码后数据包大小可能会变大,所以需要根据实际需求来确定是否适合。
3. 固定数据包头 + 数据包体
在数据包中添加一个固定长度的数据包头,例如 4 字节,表示数据包长度,然后根据该长度读取数据包。这样在处理数据包时,就可以直接读取指定长度的数据包,而不用进行分块处理。