Reputation: 4347
I'm using LengthFieldBasedFrameDecoder
to send and receive byte[]
but client gets error java.nio.channels.ClosedChannelException
after it writes.
Here is pipeline factory;
@Override
public ChannelPipeline getPipeline() throws Exception {
String charSet = EvamProperties.charSet.get();
ChannelPipeline pipeline = Channels.pipeline();
pipeline.addLast("framer", new LengthFieldBasedFrameDecoder(1000000,0,4,0,4));//16KB
pipeline.addLast("decoder", new OneToOneDecoder() {
@Override
protected Object decode(ChannelHandlerContext channelHandlerContext, Channel channel, Object o) throws Exception {
if (!(o instanceof ChannelBuffer)) {
return o;
}
ChannelBuffer buffer = (ChannelBuffer) o;
int length = buffer.readInt();
byte[] bytes = new byte[length];
buffer.readBytes(bytes);
return bytes;
}
});
pipeline.addLast("encoder", new OneToOneEncoder() {
@Override
protected Object encode(ChannelHandlerContext channelHandlerContext, Channel channel, Object o) throws Exception {
if(!(o instanceof byte[])) {
return o;
}
ChannelBuffer buffer = ChannelBuffers.dynamicBuffer();
buffer.writeInt(((byte[]) o).length);
buffer.writeBytes((byte[])o);
return buffer;
}
});
pipeline.addLast("handler", new RawEventServerHandler());
return pipeline;
}
Client write it in this way;
channel.write(eventStr.getBytes());
In this code for debugging purposes data to send is String but I can't use StringDecoder.
Does LenghtFieldBasedDecoder
is correct method to send and receive byte[]
, if not, how can I do it?
edit:
I found that another thread actually closing the channel so java.nio.channels.ClosedChannelException
is solved but I'm still eager to learn best practices for this kind of job.
Upvotes: 3
Views: 5359
Reputation: 1658
I see 3 different use cases based on your question:
length
that is stored in the frame, you need to capture a frame as byte[length]
and transfer it to the user length
frames, you need to capture a frame as byte[length]
and transfer it to the userbyte[]
array In case of (1) the LengthFieldBasedFrameDecoder
is a right choice, it allows you to capture a frame based on the length stored in the frame. In case of (2) the FixedLengthFrameDecoder
should be enough if you know that all frames have the same size. In case of (3) you do not need any special decoder, all readable bytes could be fetched from incoming ByteBuf
and transferred to the next handler, but I'm not sure how useful is that approach in a real application since most probably you'll deal with messages of some particular type/size, Netty does not guarantee how exactly the message will be split, one message can arrive as N different chunks.
Also there is ReplayingDecoder
that is useful for cases (1-2) if you want to decode incoming bytes and skip a capturing step.
Upvotes: 3