资讯专栏INFORMATION COLUMN

TCP 粘包拆包

zilu / 2796人阅读

摘要:粘包问题在这种字节流协议上做应用层分包是网络编程的基本需求。分包指的是在发生一个消息或一帧数据时,通过一定的处理,让接收方能从字节流中识别并截取还原出一个个消息。

粘包问题

在 TCP 这种字节流协议上做应用层分包是网络编程的基本需求。分包指的是在发生一个消息(message)或一帧(frame)数据时,通过一定的处理,让接收方能从字节流中识别并截取(还原)出一个个消息。因此,“粘包问题”是个伪命题

短连接分包

对于短连接的 TCP 服务,分包不是一个问题,只要发送方主动关闭连接,就表示一个消息发送完毕,接收方 read() 返回0,从而知道消息的结尾

TCP 发送机制

为了提高 TCP 的传输效率,TCP 有一套自己的发送机制

TCP 维持一个变量,它等于最大报文段长度 MSS。只要缓存中存放的数据达到 MSS 字节时,就组装成一个 TCP 报文段发送出去

由发送方的应用进程指明要求发送报文段,即 TCP 支持的推送(push)操作

发送方的一个计时器期限到了,这时把当前已有的缓存数据装入报文段(但长度不能超过 MSS)发送出去

长连接分包

对于长连接的 TCP 服务,分包有四种方法

消息长度固定

使用特殊的字符或字符串作为消息的边界,例如 HTTP 协议的 headers 以“rn”为字段的分隔符

在每条消息的头部加一个长度字段,这恐怕是最常见的做法

利用消息本身的格式来分包,例如 XML 格式的消息中 ... 的配对,或者 JSON 格式中的 { ... } 的配对。解析这种消息格式通常会用到状态机(state machine)

复杂的分包

假如消息格式非常简单,“消息”本身是一个字符串,每条消息有一个4字节的头部,以网络序存放字符串的长度。消息直接没有间隙,字符串也不要求以 "0" 结尾

发送两条消息“hello”和“smartboy”,打包后的字节流共有21字节

0x00, 0x00, 0x00, 0x05, "h", "e", "l", "l", "o",
0x00, 0x00, 0x00, 0x08, "s", "m", "a", "r", "t", "b", "o", "y"

假设数据最终都全部到达,数据解析逻辑至少能正确处理以下各种数据到达的次序

一个字节一个字节到达

数据分两次到达,第一次收到2个字节,不足消息的长度字段

数据分两次到达,第一次收到4个字节,刚好够长度字段,但是没有 body

数据分两次到达,第一次收到8个字节,长度完整,但 body 不完整

数据分两次到达,第一次收到9个字节,长度完整,但 body 也完整

数据分两次到达,第一次收到10个字节,第一条消息的长度完整、body 也完整,第二条消息长度不完整

请自行移动和增加分割点,一共有超过 100 万种可能(221-1)

数据一次就全部到达

《TCP粘包拆包》 原文链接:https://blog.maplemark.cn/2019/04/tcp粘包拆包.html?utm=sf

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/31358.html

相关文章

  • php - tcp 粘包/拆包实例

    摘要:长链接模式下,使用固定消息头长度的方式进行消息拆包,解决粘包问题。但如果是短连接多个消息或长链接模式下,就可能会发生粘包,客户端不关闭服务端无法通过确定消息读取完毕的问题。这就需要定义协议和拆包。 tcp 长链接模式下,使用固定消息头长度的方式进行消息拆包,解决粘包问题。 固定消息头协议 将消息头的前N个字节固定为消息长度位,结合业务场景,2bytes 或 4bytes,读取消息时先读...

    Blackjun 评论0 收藏0
  • Netty(三) 什么是 TCP 拆、粘包?如何解决?

    摘要:是一个面向字节流的协议,它是性质是流式的,所以它并没有分段。可基于分隔符解决。编解码的主要目的就是为了可以编码成字节流用于在网络中传输持久化存储。 showImg(https://segmentfault.com/img/remote/1460000015895049); 前言 记得前段时间我们生产上的一个网关出现了故障。 这个网关逻辑非常简单,就是接收客户端的请求然后解析报文最后发送...

    YanceyOfficial 评论0 收藏0
  • 高并发 - 收藏集 - 掘金

    摘要:在中一般来说通过来创建所需要的线程池,如高并发原理初探后端掘金阅前热身为了更加形象的说明同步异步阻塞非阻塞,我们以小明去买奶茶为例。 AbstractQueuedSynchronizer 超详细原理解析 - 后端 - 掘金今天我们来研究学习一下AbstractQueuedSynchronizer类的相关原理,java.util.concurrent包中很多类都依赖于这个类所提供的队列式...

    levius 评论0 收藏0
  • 高并发 - 收藏集 - 掘金

    摘要:在中一般来说通过来创建所需要的线程池,如高并发原理初探后端掘金阅前热身为了更加形象的说明同步异步阻塞非阻塞,我们以小明去买奶茶为例。 AbstractQueuedSynchronizer 超详细原理解析 - 后端 - 掘金今天我们来研究学习一下AbstractQueuedSynchronizer类的相关原理,java.util.concurrent包中很多类都依赖于这个类所提供的队列式...

    fantix 评论0 收藏0
  • 【Java】几道让你拿offer的面试题

    摘要:的方法,的默认实现会判断是否是类型注意自动拆箱,自动装箱问题。适应自旋锁锁竞争是下的,会经过用户态到内核态的切换,是比较花时间的。在中引入了自适应的自旋锁,说明自旋的时间不固定,要不要自旋变得越来越聪明。 前言 只有光头才能变强 之前在刷博客的时候,发现一些写得比较好的博客都会默默收藏起来。最近在查阅补漏,有的知识点比较重要的,但是在之前的博客中还没有写到,于是趁着闲整理一下。 文本的...

    张春雷 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<