转自粘包与半包问题 - xiekun的文章 - 知乎

作者:xiekun
链接:https://zhuanlan.zhihu.com/p/401209622
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

首先,让我们来看看什么是粘包与半包问题,以及出现粘包半包问题的原因,最后我们来看看 Netty 是怎么解决粘包半包问题。
注:本文是满一航老师 netty 课程的总结,并非原创。

一、什么是粘包与半包问题

粘包问题:
现象就是,客户端发送了两句话,第一句话是 “hello”,第二句话是 “world”,但是服务端接收到的却是 “helloworld”。我们希望服务器能把两句话分开,但是两句话却粘在了一起无法分离,这就是粘包现象。
半包问题:
半包问题现象恰恰相反,客户端发送了一句话 “hello, world”。但是服务端接收到的却是 “hell” 和 “o, world” 两句话。我们希望服务器能收到一整句话,但是服务器却收到了两句分离的话,这就是半包现象。

二、出现粘包半包问题的原因

粘包问题的原因:

  • 应用层:接收方 ByteBuf 设置太大(Netty 默认 1024)
  • 滑动窗口:假设发送方 256 bytes 表示一个完整报文,但由于接收方处理不及时且窗口大小足够大,这 256 bytes 字节就会缓冲在接收方的滑动窗口中,当滑动窗口中缓冲了多个报文就会粘包
  • Nagle 算法:会造成粘包

半包问题的原因:

  • 应用层:接收方 ByteBuf 小于实际发送数据量
  • 滑动窗口:假设接收方的窗口只剩了 128 bytes,发送方的报文大小是 256 bytes,这时放不下了,只能先发送前 128 bytes,等待 ack 后才能发送剩余部分,这就造成了半包
  • MSS(MTU) 限制:当发送的数据超过 MSS 限制后,会将数据切分发送,就会造成半包

    三、粘包半包问题的解决方案

  1. 短链接,发一个包建立一次连接,这样连接建立到连接断开之间就是消息的边界,缺点效率太低
  2. 每一条消息采用固定长度,缺点浪费空间
  3. 每一条消息采用分隔符,例如 \n,缺点需要转义
  4. 每一条消息分为 head 和 body,head 中包含 body 的长度