简体   繁体   中英

Netty - Correct usage of a decoder

I have once again a question about Netty.

My scenario is:

incoming message (TCP) = header[byte,int,byte] body[bytes]

I have a packet class which holds the header & body with some methods. My channel pipeline is:

ProtocolDecoder > SessionHandler

My idea of the ProtocolDecoder is that it receives a message, splits it up and creates a Packet variable to pass on to the next handler in the pipeline.

The code of the ProtocolDecoder class:

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

}

The SessionHandler has this code:

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

So my two questions are:

  • Is this the correct usage of the ByteToMessageDecoder?
  • How do I solve the error: "java.lang.UnsupportedOperationException: direct buffer" when I access the direct buffer ( array() method) in the toString() method of the packet?

UPDATE:

I remade the decoder like supposed to and this is my outcome: http://pastebin.com/wQz2LbYT

I wasn't sure if I had to put the code here because this post would become pretty big. Anyways it seems to work fine now :) thanks alot!

You don't use the ByteToMessageDecoder correctly as once you add something to the List (out) it will be removed once the method returns and forwarded to the next ChannelInboundHandler in the ChannelPipeline. If you need to hold a reference to your packet until you add it to out use a field in the class for it.

You can only access the array() if hasArray() returns true. Otherwise the buffer itself is backed by native memory. In this case you will need to use one of its getBytes(...) methods to copy the content to an array. That said if you only want to get the content of the buffer as string you can use ByteBuf.toString(Charset) for this.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM