使用Netty 5对多种不同类型进行编码和解码

时间:2014-04-29 23:28:09

标签: java networking netty

我正在尝试实现具有多种不同数据包类型的网络协议。我面临的问题是最适合的问题。用Netty实现这一点的方法。我先发布一些课程,然后描述我想要完成的课程。

public class ItemStack {

    public ItemStack(final int item, final int amount) {
        if (item < 0) {
            throw new IllegalArgumentException("item must be non-negative integer: " + item);
        }
        if (amount < 1) {
            throw new IllegalArgumentException("amount must be positive integer: " + amount);
        }
        this.item = item;
        this.amount = amount;
    }

    public int getItem() {
        return item;
    }

    public int getAmount() {
        return amount;
    }

    private final int item;
    private final int amount;
}
public class ChatMessage {

    public ChatMessage(final String playerName, final String message) {
        if (playerName == null) {
            throw new IllegalArgumentException("playerName must not be null");
        }
        if (message == null) {
            throw new IllegalArgumentException("message must not be null");
        }
        this.playerName = playerName;
        this.message = message;
    }

    public String getPlayerName() {
        return playerName;
    }

    public String getMessage() {
        return message;
    }

    private final int playerName;
    private final int message;
}

现在,通过网络传输的所有POJO都将具有数据包标识符。这将是一个1字节的代码,让解码器知道它是什么类型的数据包,以及如何解码它。

处理此案件最合适的方法是什么?如果有一个PacketDecoder类扩展ByteToMessageDecoder,读取一个字节,确定类型,然后在同一个类中,使用适当的方法对数据包进行解码(如下所示:

public class PacketDecoder extends ByteToMessageDecoder {

    protected void decode(
        final ChannelHandlerContext context, final ByteBuf buf, List<Object> objects) throws Exception {
        if (buf.readableBytes < 1) {
            return;
        }
        final int opcode = buf.readByte() & 0xff;
        final Packet packet = decodePacket(opcode);
        objects.add(packet);
    }

    private Packet decodePacket(final int opcode, final ByteBuf buf) {
        if (buf == null) {
            throw new IllegalArgumentException("buf must not be null");
        }
        Packet packet = null;
        switch (opcode) {
            case 0:
                packet = decodeItemStack(buf);
                break;

            case 1:
                packet = decodeChatMessage(buf);
                break;
            // ...
        }
        return packet;
    }
}

或者将每种类型的解码器添加到管道中会更好吗?

1 个答案:

答案 0 :(得分:3)

我是在自己的程序中完成的,我使用的是单个解码器,因为它更直接。我可以看到想要多个解码器的唯一原因是,如果需要扩展或动态更改服务器理解的协议。例如,您的服务器的某些方面可能是免费的,其他方面是为许可证密钥开启的扩展支付的,那么我可以看到这种架构很重要。或者您可以动态加载协议的扩展名。我认为你需要一个真正的理由将解码分段为几个解码器,除了它在架构上纯粹。

在这种情况下,您可以向管道添加多个解码器,但每个解码器需要播放不适合它的好的转发数据包到管道中的下一个解码器。您还必须注意不要将解码器可能需要的下游字节拉出来。

这是我不会做的。每个消息架构的解码器。编写和维护将非常麻烦。由于写入每个解码器的开销都是为了播放良好的转发数据包,因此每次编写解码器时都不会进行该练习。你可以通过一个很好的基类来解决这个问题,但是为什么要解决第一个字节并做一个简单的梯形图来解决所有麻烦呢?