通过扩展MessageToByteEncoder和ByteToMessageDecoder来自定义编解码器
- 原理
使用int数据类型来记录整个消息的字节数组长度,然后将该int数据作为消息的消息头一起传输
服务端接收消息数据时,先接收4个字节的int数据类型数据,此数据即为整个消息字节数组的长度,再接收剩余字节,直到接收的字节数组长度等于最先接收的int数据类型数据大小,即字节数组的长度
类似protobuf
- 消息格式
length | Message Data
- LengthFieldPrepender与LengthFieldBasedFrameDecoder原理
- 代码
继续使用Netty对Protobuf的解决粘包/半包问题的编解码方案中的UserInfo
1.CustomServer
/**
* @author pdc
*/
public class CustomServer {
public void bind(int port) throws Exception {
//配置服务端的NIO线程组
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 100)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
//解决粘包/半包,根据消息长度自动拆包
ch.pipeline().addLast(new LengthFieldBasedFrameDecoder(65535, 0, 2, 0, 2));
//配置自定义序列化解码工具
ch.pipeline().addLast(new CustomV1Decoder());
//解决粘包/半包问题附加消息长度在消息头部
ch.pipeline().addLast(new LengthFieldPrepender(2));
//配置自定义序列化编码工具
ch.pipeline().addLast(new CustomV1Encoder());
ch.pipeline().addLast(new