当前位置: 首页 > 后端技术 > Java

netty系列:自定义编解码器需要注意的问题

时间:2023-04-01 15:41:52 Java

介绍在之前的系列文章中,我们提到netty中的channel只接受ByteBuf类型的对象。如果不是ByteBuf对象,则需要进行编码和解码。转换器对其进行转换。今天就来说说netty的自定义编解码器实现中需要注意的问题。自定义编码器和解码器的实现在介绍netty自带的编码器和解码器之前,我先说一下如何实现自定义编码器和解码器。netty中所有的编码器和解码器都派生自ChannelInboundHandlerAdapter和ChannelOutboundHandlerAdapter。对于ChannelOutboundHandlerAdapter,最重要的两个类是MessageToByteEncoder和MessageToMessageEncoder。MessageToByteEncoder将消息编码到ByteBuf中。这个类也是我们自定义编码最常用的类。继承这个类,实现encode方法即可。请注意,此类具有通用类型,它指定消息的对象类型。例如,如果我们想将Integer转换为ByteBuf,我们可以这样写:);}}MessagerToMessage是消息和消息之间的转换,因为消息不能直接写入通道,所以需要和MessageToByteEncoder配合使用。下面是一个整数到字符串的例子:对于ChannelInboundHandlerAdapter,最重要的两个类是ByteToMessageDecoder和MessageToMessageDecoder。ByteToMessageDecoder将ByteBuf转换为对应的消息类型。我们需要继承这个类并实现decode方法。下面是一个方法,它从ByteBuf中读取所有可读字节,并将结果放入一个新的ByteBuf中。公共类SquareDecoder扩展ByteToMessageDecoder{@Overridepublicvoiddecode(ChannelHandlerContextctx,ByteBufin,Listout)throwsException{out.add(in.readBytes(in.readableBytes()));}}MessageToMessageDecoder是消息与消息之间的转换,只需要实现decode方法即可,如下实现String到Integer的转换:Listout)throwsException{out.add(message.length());}}ReplayingDecoder上面的代码看起来很简单,但是在实现的过程中还是有一些需要注意的问题。对于Decoder,我们从ByteBuf中读取数据并进行转换。但是在读取过程中,ByteBuf中数据的变化是未知的。有可能在读取过程中ByteBuf没有准备好,所以读取时需要检查ByteBuf中可读字节的大小。法官。例如,我们需要分析一个数据结构。这个数据结构的前4个字节是一个int,表示字节数组的长度。我们需要先判断ByteBuf中是否有4个字节,然后读取这4个字节作为Byte数组的长度,再读取这个长度的Byte数组,最后得到要读取的结果。如果其中一个步骤出现问题,或者可读字节长度不够,那么需要直接返回,等待下一次读取。如下:publicclassIntegerHeaderFrameDecoderextendsByteToMessageDecoder{@Overrideprotectedvoiddecode(ChannelHandlerContextctx,ByteBufbuf,Listout)throwsException{if(buf.readableBytes()<4){return;}buf.mark)ReaderIndex;intlength=buf.readInt();if(buf.readableBytes(){privateintlength;publicIntegerHeaderFrameDecoder(){//设置初始状态。超级(MyDecoderState.READ_LENGTH);}@Overrideprotectedvoiddecode(ChannelHandlerContextctx,ByteBufbuf,Listout)throwsException{switch(state()){caseREAD_LENGTH:length=buf.readInt();}检查点(MyDecoderState.READ_CONTENT);caseREAD_CONTENT:ByteBufframe=buf.readBytes(length);检查点(MyDecoderState.READ_LENGTH);添加(框架);休息;默认值:抛出新错误(“不应该到达这里。”);第二个问题是同一个实例的解码方法可能会被调用多次,如果我们在如果ReplayingDecoder中有私有变量,需要考虑清理私有变量,避免多次调用造成数据污染。总结通过继承上面的类,我们可以自己实现编解码的逻辑。但是好像还是有些问题。自定义编解码太复杂?还需要确定要读取的字节数组的大小。有更容易的方法吗?不错,敬请期待netty系列的下一篇文章:netty自带的编码器和解码器。本文示例请参考:learn-netty4本文已收录于http://www.flydean.com/14-netty-cust-codec/最通俗的解读,最深刻的干货,最简洁的教程,很多你不知道的小技巧等你来发现!欢迎关注我的公众号:《程序那些事儿》,懂技术,更懂你!