使用Netty 5编码和解码多种不同的类型 [英] Encoding and Decoding multiple different types with Netty 5

查看:765
本文介绍了使用Netty 5编码和解码多种不同的类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用多种不同的数据包类型来实现网络协议.我面临的问题是用Netty实现此问题的最正确"方式.我将首先发布一些课程,然后描述我要完成的工作.

I am trying to implement a network protocol with multiple different packet types. The problem I am facing is the most "proper" way of implementing this with Netty. I'll post some classes first, and then describe what I want to accomplish.

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字节的代码,它将使解码器知道它是什么类型的数据包,以及如何对其进行解码.

Now, all POJO that are transmitted across the network will have a packet identifier. This will be a 1-byte code that will let the decoder know what type of packet it is, and how to decode it.

处理此案的最合适方法是什么?最好有一个PacketDecoder类来扩展ByteToMessageDecoder,该类读取一个字节,确定类型,然后在同一个类中,使用适当的方法对数据包进行解码,这样更好(更常规):

What would be the most appropriate way of handling this case? Would it be better (read more conventional) to have one PacketDecoder class that extends the ByteToMessageDecoder which reads one byte, determines the type, and then in that same class, decode the packet with the appropriate method like so:

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;
    }
}

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

Or would it be better to just add every type of decoder to the pipeline?

推荐答案

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

I did this in my own program and I used a single decoder because it was more straight forward thing to do. The only reason I could see for wanting multiple decoders would be if need to extend or dynamically changing the protocol your server understands. For example, maybe certain aspects of your server are free and others are paid for extensions that license key turns on then I could see this architecture being important. Or you load extensions to the protocol dynamically maybe. I think you need a real reason to segment decoding into several decoders besides it being architecturally pure.

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

In this case you can add multiple decoders to the pipeline, but each decoder needs to play nice and forward packets not meant for it along to the next decoder in the pipeline. You also have to be careful not to pull bytes off that down stream decoders might need.

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

Here is what I wouldn't do. A decoder per message architecture. That will be cumbersome to write and maintain. Since there is overhead with each decoder written to play nice and forward packets I wouldn't go through that exercise each time I write a decoder. You could overcome that with a nice base class to extend, but why go through all that hassle when you can just parse the first byte and do a simple if ladder?

这篇关于使用Netty 5编码和解码多种不同的类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆