Netty - 正确使用解码器

时间:2014-08-09 19:47:11

标签: java protocols netty

我再次提出一个关于Netty的问题。

我的情景是:

传入消息(TCP)=头[byte,int,byte] body [bytes]

我有一个包含标题和数据包的数据包类。身体有一些方法。 我的频道管道是:

  

ProtocolDecoder> SessionHandler

我对ProtocolDecoder的想法是它收到一条消息,将其拆分并创建一个Packet变量以传递给管道中的下一个处理程序。

ProtocolDecoder类的代码:

public class ProtocolDecoder extends ByteToMessageDecoder {

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {

    int opCode;
    int length;
    boolean encrypt;

    if (in.readableBytes() < 6) {
        return;
    }

    if (out.size() != 1) {
        Packet pa = new Packet();
        opCode = in.readByte();
        length = in.readInt();
        encrypt = in.readByte() == 1;
        pa.setOpcode(opCode);
        pa.setEncrypted(encrypt);
        pa.setLength(length);
        out.add(pa);
        in.discardReadBytes();
    }

    Packet p = (Packet) out.get(0);

    if (in.readableBytes() >= p.getLength()) {
        p.setPayload(in.copy());
    }
    }

}

SessionHandler有以下代码:

@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
Packet p = (Packet) msg;
System.out.println("Packet: " + p.toString());
}

所以我的两个问题是:

  • 这是ByteToMessageDecoder的正确用法吗?
  • 当我在数据包的array()方法中访问直接缓冲区(toString()方法)时,如何解决错误:“java.lang.UnsupportedOperationException:direct buffer”?

更新

我重新设计了解码器,这是我的结果:http://pastebin.com/wQz2LbYT

我不确定是否必须将代码放在此处,因为这篇文章会变得非常大。无论如何它现在似乎工作正常:)非常感谢!

1 个答案:

答案 0 :(得分:4)

你没有正确使用ByteToMessageDecoder,因为一旦你向List添加了东西(out),一旦方法返回并转发到ChannelPipeline中的下一个ChannelInboundHandler,它将被删除。如果您需要保留对数据包的引用,直到将其添加到其中,请使用类中的字段。

如果hasArray()返回true,则只能访问array()。否则缓冲区本身由本机内存支持。在这种情况下,您需要使用其中一个getBytes(...)方法将内容复制到数组中。也就是说,如果您只想将缓冲区的内容作为字符串获取,则可以使用ByteBuf.toString(Charset)。