前言
极度投入,深度沉浸,边界清晰
前端小菜鸡一枚,分享的文章纯属个人见解,若有不正确或可待讨论点可随意评论,与各位同学一起学习~
什么是粘包/半包问题,该如何解决?
什么是粘包?
- 粘包问题:在数据传输时,在一条消息中读取到了另一条消息的部分数据,这种现象叫做粘包。
- 比如发送了两条消息,分别为“ABC”和“DEF”,那么正常情况下接收端也应该收到两条消息“ABC”和“DEF”,但接收端却收到的是“ABCD”,像这种情况就叫做粘包,如下图所示:
什么是半包?
- 半包问题:指接收端只收到了部分数据,而非完整的数据的情况就叫做半包。
- 比如发送了一条消息是“ABC”,而接收端却收到的是“AB”和“C”两条信息,这种情况就叫做半包,如下图所示:
为什么会出现粘包问题?
- Q: 为什么会出现粘包问题?
- R: 粘包问题发生在 TCP/IP 协议中,因为 TCP 是面向连接的传输协议,它是以 流 stream 的形式传输数据的,而 流 数据是没有明确数据的开始和结尾边界的,所以就会出现粘包问题。
如何解决粘包/半包问题?
- Q: 如何解决粘包/半包问题?
固定数据大小
:发送放和接收方固定发送数据的大小,当字符串长度不够时用空字符弥补。有了固定大小之后就知道每条消息的具体边界了,这样就没了粘包问题。- 缺点:当数据量小的时候使用空字符来填充,会额外增加网络传输的负担。
封装自定义数据协议层
:在 TCP 协议的基础上封装一层自定义数据协议,在自定义数据协议中,包含数据头(储存数据的大小) 和数据的具体内容,这样服务端得到数据后,通过解析数据头就可以知道数据的具体长度,也就没有粘包的问题了。- 缺点:此方案虽然可以解决粘包问题,但消息的设计和代码的实现复杂度比较高,所有也不是理想的解决方案
以特殊的字符结尾
: 比如\n
结尾,这样我们就知道数据的具体边界了从而避免了粘包的问题。- 缺点:优点是实现起来简单,但存在一定的局限性,比如一条消息中间如果出现了结束符就会造成半包的问题,所以如果是复杂的字符串要对内容进行编码和解码处理,这样才能保证结束符的正确性。
包头 + 包体格式
:这种格式的包一般分为两部分,即包头和包体,包头是固定大小的,且包头中必须含有一个字段来说明接下来的包体有多大。
文章特殊字符描述:
- 问题标注
Q(question)
- 答案标注
R(result)
- 注意事项标准:
A:(attention matters)
- 详情描述标注:
D:(detail info)
- 总结标注:
S:(summary)
- 分析标注:
Ana:(analysis)
- 提示标注:
T:(tips)