我正在使用LengthFieldBasedFrameDecoder
发送和接收byte[]
,但客户端在写入后会收到错误java.nio.channels.ClosedChannelException
。
这是管道工厂;
@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;
}
客户以这种方式写它;
channel.write(eventStr.getBytes());
在此代码中,为了调试目的,要发送的数据是String,但我不能使用StringDecoder。
LenghtFieldBasedDecoder
是发送和接收byte[]
的正确方法,如果没有,我该怎么办?
编辑:
我发现另一个线程实际关闭了频道,所以java.nio.channels.ClosedChannelException
已经解决但我仍然渴望学习这类工作的最佳实践。
答案 0 :(得分:3)
我根据您的问题看到了3个不同的用例:
length
的帧,您需要将帧捕获为byte[length]
并将其传输给用户length
帧,您需要将帧捕获为byte[length]
并将其传输给用户byte[]
数组如果(1)LengthFieldBasedFrameDecoder
是正确的选择,它允许您根据帧中存储的长度捕获帧。在(2)的情况下,如果您知道所有帧具有相同的大小,则FixedLengthFrameDecoder
应该足够了。在(3)的情况下你不需要任何特殊的解码器,所有可读的字节都可以从传入的ByteBuf
获取并转移到下一个处理程序,但我不确定这个方法在实际应用程序中有多大用处,因为最有可能你会处理某些特定类型/大小的消息,Netty不保证消息将如何分割,一条消息可以作为N个不同的块到达。
如果要解码传入的字节并跳过捕获步骤,还有ReplayingDecoder
对情况(1-2)有用。