Netty的入站出站与自定义编解码器

入站出站

ChannelPipeline 提供了ChannelHandler链的容器,以客户端应用程序为例,如果事件的运动方向是从客户端到服务端,称之为出站,即客户端发送给服务端的数据会通过pipeline中的一系列ChannelOutboundHandler,并被这些handler处理,反之则成为入站

编码解码器

1.当netty发送或者接受一个消息的时候,就将会发生一次数据转换,入站消息会被解码,从字节转换为另一种格式(比如java对象);如果是出站消息,它会被编码成字节。
2.netty提供一系列实用的编码解码器,他们都实现了ChannelInboundHandler或者ChannelOutboundHandler接口。在这些类中,channelRead方法已经被重写了,以入站为例,对于每个从入站Channel读取的消息,这个方法会被调用,随后,它将调用由解码器所提供的decode()方法进行解码,并将已经解码的字节转发给ChannelPipeline中的下一个ChannelInboundHandler

解码器ByteToMessageDecoder

1.继承关系图:
在这里插入图片描述
2.由于不可能知道远程节点是否会一次性发送一个完整的信息,tcp有可能出现粘包拆包的问题,这个类会对入站数据进行缓冲,知道它准备好被处理。

Netty链式调用机制:

编码解码器在进行编码或者解码结束时,会将转发给Pipeline中的下一个handler,具体执行流程为:

在这里插入图片描述

自定义编码器与解码器

编码器:

package com.jym.codeHandler;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;

/**
 * @program: NettyPro
 * @description:
 * @author: jym
 * @create: 2020/02/11
 */
public class MyLongToByteEncoder extends MessageToByteEncoder<Long> {
    @Override
    protected void encode(ChannelHandlerContext channelHandlerContext, Long msg, ByteBuf byteBuf) throws Exception {
        System.out.println("encode方法被调用");
        System.out.println("msg =" +msg);
        byteBuf.writeLong(msg);
    }
}

解码器:

package com.jym.codeHandler;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;

import java.util.List;

/**
 * @program: NettyPro
 * @description:
 * @author: jym
 * @create: 2020/02/11
 */
public class MyByteToLongDecoder extends ByteToMessageDecoder {
    /**
     * decode 会根据接受的数据,被调用多次,知道没有新的元素被添加到List,或者是ByteBuf没有更多个可读字节为止
     * 如果list 不为空,就会将list的内容传递给下一个channelInboundHandler,该处理器的方法也会被调用多次
     *
     * @param channelHandlerContext 上下文对象
     * @param byteBuf 入站的byteBuf
     * @param list list集合,将解码后的数据传给下一个集合
     * @throws Exception
     */
    @Override
    protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception {
        // long 8八个字节,大于等于8才处理
        if(byteBuf.readableBytes()>=8){
            list.add(byteBuf.readLong());
        }
    }
}
解码器 ReplayingDecoder

1.ReplayingDecoder<> extends ByteToMessageDecoder
2.ReplayingDecoder扩展了ByteToMessageDecoder类,使用这个类,我们不必调用readableBytes方法,参数S指定了用户状态管理类型,其中void代表不需要状态管理
3.应用实例
4.ReplayingDecoder使用方便,但是有局限性
并不是所有的ByteBuf操作都支持,如果调用了不被支持的方法,将会抛出一个异常
ReplayingDecoder 在某些情况下可能稍慢于ByteToMessageDecoder,例如网络缓慢并且消息格式复杂时,消息会拆成多个碎片,效率变低

Netty其他解码器

1 . lineBasedFrameDecoder: 这个类在netty内部也有使用,它使用行位控制符作为分隔符来解析数据
2. DelimiterBasedFrameDecoder:使用自定义的特殊字符作为消息的分隔符
3. HttpObjectDecoder:一个HTTP数据的解码器
4. LengthFieldBasedFrameDecoder:通过指定长度来标识整包消息,这样就可以自动的处理黏包和半包消息

学习年限不足,知识过浅,说的不对请见谅。

世界上有10种人,一种是懂二进制的,一种是不懂二进制的。

发布了78 篇原创文章 · 获赞 54 · 访问量 46万+

猜你喜欢

转载自blog.csdn.net/weixin_43326401/article/details/104275787