Netty自定义编码解码器

上次通信的时候用的是自带的编解码器,今天自己实现一下自定义的。

1、自定义一下协议

复制代码
//协议类
@Data
public class Protocol<T> implements Serializable {

    private Long id = System.currentTimeMillis();

    private short msgType;// 假设1为请求 2为响应

    private T body;
    
}

//消息请求体
@Data
public class RequestMsg implements Serializable {

    private String msg;

    private String other;

}

//消息响应体
@Data
public class ResponseMsg implements Serializable {

    private String result;

    private String error;

}

2、定义编解码器import io.netty.buffer.ByteBuf;

复制代码
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;

//编码器
public class EnCodeMsg extends MessageToByteEncoder<Protocol<Object>> {
    @Override
    protected void encode(ChannelHandlerContext channelHandlerContext, Protocol<Object> msg, ByteBuf byteBuf) throws Exception {
        Serialization serialization = new JdkSerialization();
        byte[] body = serialization.serialize(msg.getBody());
        int length = body.length;
        Long id = msg.getId();
        short msgType = msg.getMsgType();
        byteBuf.writeLong(id);
        byteBuf.writeShort(msgType);
        byteBuf.writeInt(length);
        byteBuf.writeBytes(body);
    }
}


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

import java.util.List;

//解码器
public class DeCodeMsg extends ByteToMessageDecoder {
    @Override
    protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf in, List<Object> list) throws Exception {
        Serialization serialization = new JdkSerialization();
        long id = in.readLong();
        short msgType = in.readShort();
        int bodyLength = in.readInt();
        int i = in.readableBytes();
        if(bodyLength!=i){
            in.resetReaderIndex();
            return;
        }
        byte[] bytes = new byte[bodyLength];
        in.readBytes(bytes);
        if(msgType==(short)1){
            Protocol<RequestMsg> requestMsgProtocol = new Protocol<>();
            RequestMsg requestMsg = serialization.deserialize(bytes, RequestMsg.class);
            requestMsgProtocol.setBody(requestMsg);
            requestMsgProtocol.setId(id);
            requestMsgProtocol.setMsgType(msgType);
            list.add(requestMsgProtocol);
        }else if(msgType==(short)2){
            Protocol<ResponseMsg> responseMsgProtocol = new Protocol<>();
            ResponseMsg responseMsg = serialization.deserialize(bytes,ResponseMsg.class);
            responseMsgProtocol.setId(id);
            responseMsgProtocol.setMsgType(msgType);
            responseMsgProtocol.setBody(responseMsg);
            list.add(responseMsgProtocol);
        }else {
            return;
        }

    }
}

3、修改消息处理器

复制代码
public class NettyClientHandler extends SimpleChannelInboundHandler<Protocol<ResponseMsg>> {

    private static final Logger logger = LoggerFactory.getLogger(NettyClientHandler.class);

    private volatile Channel channel;

    private SocketAddress remotePeer;

    public Channel getChannel() {
        return channel;
    }

    public SocketAddress getRemotePeer() {
        return remotePeer;
    }

    /**
     * 注册
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        logger.info("channelRegistered--------------");
        super.channelRegistered(ctx);
        this.channel = ctx.channel();
    }

    /**
     * 激活
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        super.channelActive(ctx);
        this.remotePeer = this.channel.remoteAddress();
        logger.info("channelActive--------------");
    }

    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext,Protocol<ResponseMsg> o) throws Exception {
        logger.info("channelRead0--------------"+Thread.currentThread().getName());
        logger.info("消费者接收到的消息为{}", JSONObject.toJSONString(o));
    }

    public void sendMsg(Protocol<RequestMsg> message){
        channel.writeAndFlush(message);
    }

    public void close(){
        channel.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);
    }

}

public class NettyServerHandler extends SimpleChannelInboundHandler<Protocol<RequestMsg>> {

    private static final Logger logger = LoggerFactory.getLogger(NettyServerHandler.class);

    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, Protocol<RequestMsg> o) throws Exception {

        logger.info("服务端收到的消息为================{}", JSONObject.toJSONString(o));
        Protocol<ResponseMsg> protocol = new Protocol<>();
        ResponseMsg responseMsg = new ResponseMsg();
        responseMsg.setResult("SUCCESS");
        responseMsg.setError("NO ERROR");
        protocol.setBody(responseMsg);
        protocol.setMsgType((short) 2);
        protocol.setId(o.getId());
        channelHandlerContext.channel().writeAndFlush(protocol);
    }
}

4、测试

复制代码
public class NettyTest {

    public static void main(String[] args) {

        new Thread(()->{
            NettyServer.startNettyServer();
        }).start();

        new Thread(()->{
            NettyClient instance = NettyClient.getInstance();
            try {
                while (true){
                    Thread.sleep(2000);
                    Protocol<RequestMsg> protocol = new Protocol<>();
                    protocol.setMsgType((short)1);
                    RequestMsg requestMsg = new RequestMsg();
                    requestMsg.setMsg("hello:"+System.currentTimeMillis());
                    requestMsg.setOther("你好啊");
                    protocol.setBody(requestMsg);
                    instance.sendMsg(protocol);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

        }).start();
    }
}

5、效果截图

相关推荐
golang学习记9 分钟前
IDEA 2026年的玩法已经完全不同
java·ide·intellij-idea
紧跟先前的步伐30 分钟前
Go AI Agent 实战 05|Temperature 与生成参数:让模型输出可控
java·人工智能·golang
金銀銅鐵35 分钟前
[Java] 展示添加元素时 ArrayList 的内部变化
java·后端·ai编程
斌糖雪梨1 小时前
spring auth 核心流程详解
java·后端·spring
文丑颜不良啊2 小时前
LeetCode201~225题目解析
java·leetcode
SL_staff4 小时前
4G设备掉线三层归因指南:SIM卡、模组、JVS-IOT网关配置精准锁定
java·物联网·产品
Wang's Blog5 小时前
Java 项目实战: 交友项目 - 黑名单:取消黑名单
java·windows·交友
杨杨杨大侠5 小时前
DeepSeek Harness:连 Agent Loop 都能替换的插件架构
java·人工智能·agent
SL_staff5 小时前
私有化低代码运维三重雷区:JVS开源栈中的Kafka/ES/RabbitMQ治理实践
java·低代码·全栈
yuniko-n5 小时前
【算法】约瑟夫环问题
java·算法