前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >TCP 粘包拆包

TCP 粘包拆包

作者头像
ColinLiu
修改2019-05-05 09:55:10
1.5K0
修改2019-05-05 09:55:10
举报
文章被收录于专栏:面向offer编程面向offer编程

粘包问题

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

短连接分包

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

TCP 发送机制

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

  • TCP 维持一个变量,它等于最大报文段长度 MSS。只要缓存中存放的数据达到 MSS 字节时,就组装成一个 TCP 报文段发送出去
  • 由发送方的应用进程指明要求发送报文段,即 TCP 支持的推送(push)操作
  • 发送方的一个计时器期限到了,这时把当前已有的缓存数据装入报文段(但长度不能超过 MSS)发送出去

长连接分包

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

  • 消息长度固定
  • 使用特殊的字符或字符串作为消息的边界,例如 HTTP 协议的 headers 以“\r\n”为字段的分隔符
  • 在每条消息的头部加一个长度字段,这恐怕是最常见的做法
  • 利用消息本身的格式来分包,例如 XML 格式的消息中 <root>...</root> 的配对,或者 JSON 格式中的 { ... } 的配对。解析这种消息格式通常会用到状态机(state machine)

复杂的分包

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

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

代码语言:txt
复制
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 万种可能(2<sup>21-1</sup>)
  • 数据一次就全部到达

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系转载前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 粘包问题
  • 短连接分包
  • TCP 发送机制
  • 长连接分包
  • 复杂的分包
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档