How to properly handle decoder chain in netty?
Frederic Bregier
fredbregier at free.fr
Wed Jun 3 01:44:59 EDT 2009
Hi Jiang,
I will only focus on some points, hoping this can help you.
First, on ChannelHandlerContext, if you refer to the API (see
http://www.jboss.org/file-access/default/members/netty/freezone/api/3.1/org/jboss/netty/channel/ChannelHandlerContext.html
ChannelHandlerContext.html ),
it says that a context is unique for each couple channel/handler, which
means
the two decoders will not share the same context.
According to the API, even several instance of the same handler class will
result in different context.
And even several entries of the same handler object in the same pipeline
will result in different context.
As you rely on the context between the two decoder handlers, and as they
should not share
any context (they are different object even if they are in the same
pipeline), and thus the context attachment should be different.
You could use ChannelLocal for this or passing to the next decoder an object
that have
both the JigDFSCommand and the buffer as attributes, then getting this
object
in the second decoder directly.
Also another point, is it ok for your program to have a "System.exit(-1)" in
the first decoder?
Your server will immediately stop, even if they are other clients connected.
If this is the behaviour you wanted, that's fine. However I would suggest
you to cleanly
close the connection in order to not have "opened" port on your server...
If this is not what you wanted, perhaps what you need is to close the
channel
immediately and not passing to the next decoder (for instance, returning
null
from the decoder method could prevent the next steps in the next decoder in
the pipeline).
Another way (probably better) is to throw an exception and to get it in the
last handler and to close the
connection there.
HTH,
Frederic
Jiang Bian wrote:
>
> I am just wondering whether I am doing the right thing. Don't want to walk
> on the wrong path too far...
>
> I am doing a customized binary protocol. Here is my pipeline factory
>
> @Override
> public ChannelPipeline getPipeline() throws Exception {
> ChannelPipeline p = pipeline();
> p.addLast("logger", new LoggingHandler(true));
> p.addLast("jigdfsDecoder", new JigDFSCommandDecoder());
> p.addLast("chunkDecoder", new FileChunkDecoder());
> p.addLast("handler", new NodeServerHandler(this.node));
> return p;
> }
>
> As you might have guessed, every message in my system starts with a magic
> number, followed by another integer indicates the command. So I have a
> JigDFSCommandDecoder() (extends OneToOneDecoder) upfront to make sure
> every message is generated by my protocol.
>
> I am also sending large files across the network. So I have a
> FileChunkDecoder (extends FrameDecoder) to decoder the ChannelBuffer to a
> Chunk object. It also do some other crazy things, verifying md5, tracking
> segment index, etc., so I didn't used LengthBasedFrameDecoder directly.
>
> Here comes the question: In the JigDFSCommandDecoder, I still return the
> Channel, and set the context attachment to be the JigDFSCommand.
>
> @Override
> protected Object decode(ChannelHandlerContext ctx, Channel channel,
> Object msg) throws Exception {
> if (!(msg instanceof ChannelBuffer)) {
> return msg;
> } else {
> ChannelBuffer buffer = (ChannelBuffer) msg;
>
> if (buffer.readableBytes() < 8) {
> return null;
> }
>
> int magicNumber = buffer.readInt();
> if (magicNumber != JigDFSCommand.JIGDFS_MAGIC_NUMBER) {
> logger.info("It's not a JigDFS message! magic number: "
> + magicNumber);
> logger.info(buffer.toString());
> System.exit(-1);
> return 0;
> }
>
> int command = buffer.readInt();
>
> ctx.setAttachment(new JigDFSCommand(command));
> return buffer;
> }
>
> }
>
> Then in the FileChunkDecoder, I am checking to see if it's ChunkData
> command.
>
> @Override
> protected Object decode(ChannelHandlerContext ctx, Channel channel,
> ChannelBuffer buffer) throws Exception {
>
> if(!(ctx.getAttachment() instanceof JigDFSCommand)){
> return null;
> }
>
> JigDFSCommand cmd = (JigDFSCommand) ctx.getAttachment();
>
> if(cmd.getJigDFSCommand() != JigDFSCommand.CHUNK_DATA){
> return null;
> }
>
> // Make sure if the segment, md5 & length fields were received.
> if (buffer.readableBytes() < 24) {
> // The length field was not received yet - return null.
> // This method will be invoked again when more packets are
> // received and appended to the buffer.
> return null;
> }
>
> ... the rest is irrelevant...
>
> }
>
> Am I doing the right thing? Or is there a better/correct way to do this?
>
> Thanks a bunch in advance,
>
> Jiang
>
>
>
>
-----
Hardware/Software Architect
--
View this message in context: http://n2.nabble.com/How-to-properly-handle-decoder-chain-in-netty--tp3015408p3016523.html
Sent from the Netty User Group mailing list archive at Nabble.com.
More information about the netty-users
mailing list