龙空技术网

netty自带的四种Docoder解码器以及如何使用

程序猿伟哥 125

前言:

当前小伙伴们对“netty encoder decoder”都比较着重,朋友们都想要分析一些“netty encoder decoder”的相关资讯。那么小编在网络上收集了一些关于“netty encoder decoder””的相关内容,希望你们能喜欢,大家快快来了解一下吧!

在这里放一下自己对netty长度解码器的理解

想看netty自定义解码器讲解可以直接跳过我自定义的编解码器

开始写之前文章的netty+动态代理的项目的时候,刚开始自己在网上找了一些编码器和解码器的写法,(不完全是自定义,也用到了Kyro)自定义写了一套,直接发送你要发的实体对象,算是先理解一下编解码器的原理。

KyroMsgDecoder

public class KyroMsgDecoder extends ByteToMessageDecoder {    public static final int HEAD_LENGTH = 4;    private Kryo kryo = new Kryo();        @Override    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {        if (in.readableBytes() < HEAD_LENGTH) {        	return;        }        in.markReaderIndex();        int dataLength = in.readInt();        if (dataLength < 0) {        	ctx.close();        }        if (in.readableBytes() < dataLength) {            in.resetReaderIndex();            return;        }        byte[] body = new byte[dataLength];        in.readBytes(body);        Object o = convertToObject(body);                           out.add(o);    }    private Object convertToObject(byte[] body) {        Input input = null;        ByteArrayInputStream bais = null;        try {            bais = new ByteArrayInputStream(body);            input = new Input(bais);            return kryo.readObject(input, Student.class);//这是重点,这个Student就是我的实体类        } catch (KryoException e) {            e.printStackTrace();        }finally{            IOUtils.closeQuietly(input);            IOUtils.closeQuietly(bais);        }        return null;    }}12345678910111213141516171819202122232425262728293031323334353637383940
KyroMsgEncoder
public class KyroMsgEncoder extends MessageToByteEncoder<Student> {    private Kryo kryo = new Kryo();	//encode的参数直接写成实体类类型。    @Override    protected void encode(ChannelHandlerContext ctx, Student msg, ByteBuf out) throws Exception {        byte[] body = convertToBytes(msg);        int dataLength = body.length;        out.writeInt(dataLength);        out.writeBytes(body);    }	//这里也是    private byte[] convertToBytes(Student student) {        ByteArrayOutputStream bos = null;        Output output = null;        try {            bos = new ByteArrayOutputStream();            output = new Output(bos);            kryo.writeObject(output, student);            output.flush();            return bos.toByteArray();        } catch (KryoException e) {            e.printStackTrace();        }finally{            IOUtils.closeQuietly(output);            IOUtils.closeQuietly(bos);        }        return null;    }}123456789101112131415161718192021222324252627282930313233

netty提供了强大的编解码器框架,使得我们编写自定义的编解码器很容易,也容易封装重用。

在网络应用中需要实现某种编解码器,将原始字节数据与自定义的消息对象进行互相转换。网络中都是以字节码的数据形式来传输数据的,服务器编码数据后发送到客户端,客户端需要对数据进行解码。编解码器由两部分组成:编码器、解码器。

解码器:负责将消息从字节或其他序列形式转成指定的消息对象。

编码器:将消息对象转成字节或其他序列形式在网络上传输。

netty自带解码器

LineBasedFrameDecoder

LineBasedFrameDecoder是回车换行解码器,如果发送的消息以回车换行符结束标识,可以用LineBasedFrameDecoder进行解码。

@Overrideprotected void initChannel(SocketChannel arg) throws Exception {arg.pipeline().addLast(new LineBasedFrameDecoder(1024));arg.pipeline().addLast(new StringDecoder());arg.pipeline().addLast(new UserServerHandler());}123456

DelimiterBasedFrameDecoder

DelimiterBasedFrameDecoder是分隔符解码器,用户可以指定消息结束的分隔符,它可以自动选择分隔符。

@Overridepublic void initChannel(SocketChannel ch) throws Exception {    ByteBuf delimiter = Unpooled.copiedBuffer("$_".getBytes());   ch.pipeline().addLast(new DelimiterBasedFrameDecoder(1024,delimiter));   ch.pipeline().addLast(new StringDecoder());   ch.pipeline().addLast(new UserServerHandler());}}12345678

FixedLengthFrameDecoder

FixedLengthFrameDecoder是固定长度解码器,它能够按照指定的长度对消息进行自动解码,开发者不需要考虑TCP的粘包/拆包等问题,网上说是很实用的。

LengthFieldBasedFrameDecoder(我用的解码器!!!)

Netty提供了LengthFieldBasedFrameDecoder,自动屏蔽TCP底层的拆包和粘包问题,只需要传入正确的参数,即可轻松解决“读半包“问题。

@Override    protected void initChannel(SocketChannel ch) throws Exception {        /***         maxFrameLength - 发送的数据包最大的长度         lengthFieldOffset - 长度域偏移量,长度域位于整个数据包字节数组中的下标         lengthFieldLength - 长度域自己的字节数长度         lengthAdjustment – 长度域的偏移量矫正。 如果长度域的值,还包含了其他域(如长度域自身)长度,那么值为:包长 - 长度域的值 – 长度域偏移 – 长度域长         initialBytesToStrip – 丢弃的起始字节数。丢弃处于有效数据前面的字节数量。         ***/        ch.pipeline().addLast(new LengthFieldBasedFrameDecoder(1024,2,4,-4,6));        ch.pipeline().addLast(new StringDecoder(Charset.forName("UTF-8")));        ch.pipeline().addLast(new ClientHandler());        ch.pipeline().addLast(new StringEncoder());    }1234567891011121314

标签: #netty encoder decoder