Netty-TCP 01.编解码

发布时间 2023-06-30 20:01:21作者: 米虫2022

本文是使用Netty开发一个简单的TCP通讯(聊天)应用程序的第【1】部分,主要介绍编解码实现。

定制协议

一般来说,开发TCP通讯应用程序,定制通讯协议是不可避免的,这里以一种最简单的协议为例,假设一个TCP通讯数据包,包含三部分:

[type][size][content]
  1. type:数据包类型(长度为一个字节,即1个byte)
  2. size:数据包长度(长度为四个字节,即4个byte)
  3. content:实际的数据包内容

Java数据包结构封装:

/**
 * @author michong
 */
public class Packet {
    /**
     * 消息类型
     */
    private byte type;
    /**
     * 内容长度(不含size和type长度)
     */
    private int size;
    /**
     * 消息内容
     */
    private byte[] content;
}

数据编码

使用Netty进行数据包编码可以通过继承MessageToByteEncoder来实现:

/**
 * @author michong
 */
public class PacketEncoder extends MessageToByteEncoder<Packet> {

    @Override
    protected void encode(ChannelHandlerContext ctx, Packet packet, ByteBuf out) {
        if (Objects.isNull(packet) {
            return;
        }
        out.writeByte(packet.getType());
        out.writeIntLE(packet.getSize());
        out.writeBytes(packet.getContent());
    }
}

需要注意的是:这里需要按定制协议的顺序写出,这里的size使用的是小端模式,解码的时候也要使用小端模式。

数据解码

使用Netty进行数据包编码可以通过继承ReplayingDecoder来实现:

/**
 * @author michong
 */
public class PacketDecoder extends ReplayingDecoder<Void> {

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
        byte type = in.readByte();
        int size = in.readIntLE();
        byte[] content = new byte[size];
        in.readBytes(content);
        Packet pkt = new Packet(type, content);
        out.add(pkt);
    }
}

这里可以很明显的感受到使用Netty开发的好处,使用Netty开发可以不用自己处理粘包、半包问题,解码这里使用的是跟编码一样的小端模式。