Netty - 粘包和半包(上)

在网络传输中,粘包和半包应该是最常出现的问题,做为 Java 中最常使用的 NIO 网络框架 Netty,它又是如何解决的呢?今天就让咱们来看看。 git

定义

TCP 传输中,客户端发送数据,实际是把数据写入到了 TCP 的缓存中,粘包和半包也就会在此时产生。github

客户端给服务端发送了两条消息ABCDEF,服务端这边的接收会有多少种状况呢?有多是一次性收到了全部的消息ABCDEF,有多是收到了三条消息ABCDEF缓存

上面所说的一次性收到了全部的消息ABCDEF,相似于粘包。若是客户端发送的包的大小比 TCP 的缓存容量小,而且 TCP 缓存能够存放多个包,那么客户端和服务端的一次通讯就可能传递了多个包,这时候服务端从 TCP 缓存就可能一下读取了多个包,这种现象就叫粘包网络

上面说的后面那种收到了三条消息ABCDEF,相似于半包。若是客户端发送的包的大小比 TCP 的缓存容量大,那么这个数据包就会被分红多个包,经过 Socket 屡次发送到服务端,服务端第一次从接受缓存里面获取的数据,实际是整个包的一部分,这时候就产生了半包(半包不是说只收到了全包的一半,是说收到了全包的一部分)。框架

产生缘由

其实从上面的定义,咱们就能够大概知道产生的缘由了。性能

粘包的主要缘由:编码

  1. 发送方每次写入数据 < 套接字(Socket)缓冲区大小
  2. 接收方读取套接字(Socket)缓冲区数据不够及时

半包的主要缘由:code

  1. 发送方每次写入数据 > 套接字(Socket)缓冲区大小
  2. 发送的数据大于协议的 MTU (Maximum Transmission Unit,最大传输单元),所以必须拆包

其实咱们能够换个角度看待问题:cdn

  1. 收发的角度看,即是一个发送可能被屡次接收,多个发送可能被一次接收。
  2. 传输的角度看,即是一个发送可能占用多个传输包,多个发送可能共用一个传输包。

根本缘由,实际上是get

TCP 是流式协议,消息无边界。

(PS : UDP 虽然也能够一次传输多个包或者屡次传输一个包,但每一个消息都是有边界的,所以不会有粘包和半包问题。)

解决方法

就像上面说的,UDP 之因此不会产生粘包和半包问题,主要是由于消息有边界,所以,咱们也能够采起相似的思路。

改为短链接

将 TCP 链接改为短链接,一个请求一个短链接。这样的话,创建链接到释放链接之间的消息即为传输的信息,消息也就产生了边界。

这样的方法就是十分简单,不须要在咱们的应用中作过多修改。但缺点也就很明显了,效率低下,TCP 链接和断开都会涉及三次握手以及四次握手,每一个消息都会涉及这些过程,十分浪费性能。

所以,并不推介这种方式。

封装成帧

封装成帧(Framing),也就是本来发送消息的单位是缓冲大小,如今换成了帧,这样咱们就能够自定义边界了。通常有4种方式:

固定长度

这种方式下,消息边界也就是固定长度便可。

优势就是实现很简单,缺点就是空间有极大的浪费,若是传递的消息中大部分都比较短,这样就会有不少空间是浪费的。

所以,这种方式通常也是不推介的。

分隔符

这种方式下,消息边界也就是分隔符自己。

优势是空间再也不浪费,实现也比较简单。缺点是当内容自己出现分割符时须要转义,因此不管是发送仍是接受,都须要进行整个内容的扫描。

所以,这种方式效率也不是很高,但能够尝试使用。

专门的 length 字段

这种方式,就有点相似 Http 请求中的 Content-Length,有一个专门的字段存储消息的长度。做为服务端,接受消息时,先解析固定长度的字段(length字段)获取消息总长度,而后读取后续内容。

优势是精肯定位用户数据,内容也不用转义。缺点是长度理论上有限制,须要提早限制可能的最大长度从而定义长度占用字节数。

所以,十分推介用这种方式。

其余方式

其余方式就各不相同了,好比 JSON 能够当作是使用{}是否成对。这些优缺点就须要你们在各自的场景中进行衡量了。

Netty 中的实现

Netty 支持上文所讲的封装成帧(Framing)中的前三种方式,简单介绍下:

方式 解码 编码
固定长度 FixedLengthFrameDecoder 简单
分割符 DelimiterBasedFrameDecoder 简单
专门的 length 字段 LengthFieldBasedFrameDecoder LengthFieldPrepender

总结

今天主要介绍了粘包和半包问题、解决思路和 Netty 中的支持,我会在下一篇文章里重点讲述 Netty 中的具体实现,敬请期待。

有兴趣的话能够访问个人博客或者关注个人公众号、头条号,说不定会有意外的惊喜。

death00.github.io/

相关文章
相关标签/搜索