Netty的编解码器案例

一、编码的意义

编码的理解 通常指将某种数据从一种形式转换为另一种形式的过程,例如将文本从 ASCII 编码转换为 UTF-8 编码。编码是为了让数据能够在不同的系统之间进行传递,以便数据可以被正确地解释和处理。解码则是这个过程反过来。

序列化是编码吗?

  1. 序列化则是将一个数据结构对象转换为可存储或传输的格式的过程。这通常涉及将对象转换为二进制或文本格式。序列化的目的是为了在需要时能够重新创建对象,或者在不同的应用程序之间传递数据。
  2. 编码是为了确保数据被正确地解释和处理,而序列化是为了在需要时能够重新创建对象或在不同的应用程序之间传递数据。
  3. 序列化是编码的一种形式。序列化是将数据结构或对象转换为二进制格式,以便将其存储在文件中或通过网络传输。这个过程可以被视为对原始数据进行编码。在反序列化时,可以将二进制数据解码为原始数据结构或对象。

JAVA序列化

  1. java序列化对象主要是实现Serializable接口来标记序列化并生成序列化id,然后就能通过ObjectInput和ObjectOutput来完成序列化和反序列化
  2. 目的:序列后才可进行传输、或者保存。
  3. 缺点:无法跨语言、序列化后太大了、序列化过程性能低下。

二、Netty编解码器介绍

编解码器的必要性
网络应用中的数据传输,需要将原始字节数据转换成对应的自定义消息对象。服务器编码数据后发送到客户端,客户端接收字节数据后解码还原成服务端发送的消息对象。

  • 解码器:负责将消息从字节或其他序列形式转成指定的消息对象。
  • 编码器:将消息对象转成字节或其他序列形式在网络上传输。

Netty的编解码器功能

  • Netty 的编(解)码器实现了 ChannelHandlerAdapter,也是一种特殊的 ChannelHandler,所以依赖于 ChannelPipeline,可以将多个编(解)码器链接在一起,以实现复杂的转换逻辑。
  • Netty里面的编解码: 解码器:负责处理“入站 InboundHandler”数据。
  • 编码器:负责“出站OutboundHandler” 数据、

三、解码器Decoder

解码器负责 解码“入站”数据从一种格式到另一种格式,解码器处理入站数据是抽象ChannelInboundHandler的实现。需要将解码器放在ChannelPipeline中。对于解码器,Netty中主要提供了抽象基类ByteToMessageDecoder和MessageToMessageDecoder
image.png

  • ByteToMessageDecoder: 只能读取当前可用的字节数进行解码,如果数据不足则需要等待后续数据到达。他不会阻塞Channel的消息读取线程,而是将此次消息读取事件从Selector中去掉,等下一次数据到达时再继续执行解码操作。但是对于调用线程的表现就是阻塞在调用解码方法的地方。
  • ReplayingDecoder: 继承ByteToMessageDecoder,则可以使用回放机制,在数据不足时等待数据到达,之后再重复读取缓冲区的数据进行解码。,但是 ReplayingDecoder速度略慢于ByteToMessageDecoder,同时不是所有的ByteBuf都支持。
  • ByteToMessageDecoder和ReplayingDecoder 优先考虑使用 ByteToMessageDecoder。但在某些特殊场景下,比如需要处理长度不固定的数据流,或者需要精确控制解码过程中的异常情况,使用 ReplayingDecoder 可能更为适合。
  • MessageToMessageDecoder: 用于从一种消息解码为另外一种消息(例如POJO到POJO)
public class MessageDecoder extends ByteToMessageDecoder {

    @Override
    protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception {
        //开始解码
        System.out.println("解码器开始解码");

        //错误写法,不会修改缓冲区的 writerIndex readerIndex 会导致重复读取又读取为空然后报错。
        //TODO:解码器如果继承MessageToMessageDecoder 就不会报错,不知道为啥?
        //String decodeResultStr = byteBuf.toString(CharsetUtil.UTF_8);

        //解码过程
        byte[] data = new byte[byteBuf.readableBytes()];
        byteBuf.readBytes(data);
        String decodeResultStr = new String(data, CharsetUtil.UTF_8);

        //将对象添加到这个列表中,供后续的处理器使用。
        list.add(decodeResultStr);


    }
}

四、编码器Encoder

与ByteToMessageDecoder和MessageToMessageDecoder相对应,Netty提供了对应的编码器实现MessageToByteEncoder和MessageToMessageEncoder,二者都实现了ChannelOutboundHandler接口。
image.png

  • MessageToByteEncoder: 将消息转化成字节
  • MessageToMessageEncoder: 用于从一种消息编码为另外一种消息(例如POJO到POJO)
public class MessageEncoder extends MessageToByteEncoder {
    @Override
    protected void encode(ChannelHandlerContext channelHandlerContext, Object o, ByteBuf byteBuf) throws Exception {
        System.out.println("编码器开始对消息编码!");
        ByteBuf encodeBytebuf = Unpooled.copiedBuffer(o.toString(), CharsetUtil.UTF_8);
        byteBuf.writeBytes(encodeBytebuf);

    }
}

五、编解码器 Codec

编码解码器: 同时具有编码与解码功能,特点同时实现了ChannelInboundHandler和ChannelOutboundHandler接口,因此在数据输入和输出时都能进行处理。
image.png

public class MessageCodec extends MessageToMessageCodec {
    @Override
    protected void encode(ChannelHandlerContext ctx, Object msg, List out) throws Exception {
        System.out.println("编码器开始对消息编码!");
        ByteBuf encodeBytebuf = Unpooled.copiedBuffer(msg.toString(), CharsetUtil.UTF_8);
        out.add(encodeBytebuf);
    }

    @Override
    protected void decode(ChannelHandlerContext ctx, Object msg, List out) throws Exception {
        System.out.println("解码器开始解码");

        ByteBuf byteBuf = (ByteBuf) msg;
        //解码过程
        byte[] data = new byte[byteBuf.readableBytes()];
        byteBuf.readBytes(data);
        String decodeResultStr = new String(data, CharsetUtil.UTF_8);
        //将对象添加到这个列表中,供后续的处理器使用。
        out.add(decodeResultStr);
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值