Netty中的粘包与半包问题
问题引入,在Netty网络通信中常常遇见在接收端接受消息的时候会出现三中类型的输出:
- 读到一个完整的客户端输入的ByteBuf
- 读到多个客户端发过来的ByteBuf
- 读到一个客户端不完整的ByteBuf
1.1 问题
出现以上三个问题的原因是我们没有在应用层对传输层的TCP包进行包的拆分与分发。
让我们回顾一下Netty中一个网络通信的完整过程:
- 客户端的处于应用层的数据首先要发送到他自己的内核缓冲区中。
- 但是到了操作系统的内核缓冲区之后,底层会按照协议对数据包进行二次封装,封装成传输层的TCP报文。
- 之后经过传输层的一系列传输之后数据包首先发送到服务器的内核缓冲区,Netty应用程序要读取数据的时候才会将内核缓冲区的数据复制到用户态的用户缓冲区。
那么根据以上过程便产生了粘包和半包的问题:
1.每次读取底层数据缓冲区的容量是有限的,当TCP内核缓冲区中的数据比较大的时候,可能会将一个数据包分成好几块进行复制。从而导致用户进程缓冲区读到的是不完整的数据。这就导致了半包问题
2.当内核缓冲区中的数据是比较小的时候,一次复制的可能不止一个TCP的数据量。这就导致了粘包问题。
2.1 解决方案
总体来说在接受的时候Netty程序根据自定义协议将读取到进程缓冲区的数据在应用层进行二次拆分,重新组装成应用层的数据包,这个过程一般叫做分包或者拆包。
Netty中一般有两种解决方案:
- 可以自定义解码器分包器,基于ByteToMessageDecode,定义自己的用户缓冲区分包器。
- 使用Netty内置的解码器对用户缓冲区ByteBuf进行正确的分包。
以上就是Netty网络通信中的粘包和半包问题以及相应的解决方案。