我正在尝试使用多种不同的数据包类型来实现网络协议。我面临的问题是用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;
    }
}


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

最佳答案

我在自己的程序中做到了这一点,并使用了单个解码器,因为这样做更直接。我需要多个解码器的唯一原因就是是否需要扩展或动态更改服务器可以理解的协议。例如,也许您服务器的某些方面是免费的,而另一些方面是为许可证密钥打开的扩展付费的,那么我可以看到这种体系结构很重要。或者您可以动态加载协议的扩展。我认为除了架构上纯洁之外,您还需要一个真正的理由将解码分为几个解码器。

在这种情况下,您可以在管道中添加多个解码器,但是每个解码器都需要播放漂亮的数据包,并将不需要的数据包转发到管道中的下一个解码器。您还必须小心,不要拉下下游解码器可能需要的字节。

这是我不会做的。每个消息体系结构的解码器。编写和维护起来很麻烦。由于编写每个解码器来播放漂亮的转发数据包会产生开销,因此我每次编写解码器时都不会进行该练习。您可以通过扩展一个不错的基类来克服它,但是当您仅解析第一个字节并执行一个简单的if阶梯时,为什么要经历所有麻烦呢?

关于java - 使用Netty 5编码和解码多种不同类型,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/23377089/

10-13 01:11