我有一个使用Netty 3.6.6的应用程序。 我使用netty将随机数据包数据从客户端发送到服务器。
发件人使用此管道:
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
@Override
public ChannelPipeline getPipeline() {
return Channels.pipeline(
new LengthFieldPrepender(4) );
}
});
我使用ChannelBuffer包装我的数据包数据,我希望处理程序在前面加上4个字节,以便接收者可以知道数据包的开始和结束位置。
接收者使用:
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() throws Exception {
return Channels.pipeline(
new NettyReceiveHandler(listener));
}
});
public class NettyReceiveHandler extends LengthFieldBasedFrameDecoder {
@Override
protected Object decode(ChannelHandlerContext ctx, Channel channel,
ChannelBuffer buffer) throws Exception {
ChannelBuffer decodedBuffer = (ChannelBuffer) super.decode(ctx, channel, buffer);
if(decodedBuffer == null)
{
return null; // not ready yet
}
listener.handleObject(decodedBuffer);
return null; // no upstream
}
public NettyReceiveHandler(NettyRecvListener listener) {
super(THREEMiB, 0, 4, 0, 4);
this.listener = listener;
}
private static final Logger logger = Logger.getLogger(
NettyReceiveHandler.class.getName());
@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
logger.severe("Unexpected exception from downstream." + e.getCause());
e.getChannel().close();
}
private final NettyRecvListener listener;
private static final int THREEMiB = 3*1024*1024;
}
一切似乎都按预期工作。发送者一个接一个地发送随机大小的ChannelBuffers,接收者以相同的顺序接收相同的ChannelBuffers
现在我的问题是:
1.当我向通道写一个大的ChannelBuffer时,它被分解成几个写入 例如,我在日志中看到了我的测试
WARNING: The pipeline contains no upstream handlers; discarding: [id: 0xa1b55c95, /127.0.0.1:52359 => localhost/127.0.0.1:9991] WRITTEN_AMOUNT: 131071
所以我假设我发送两个1MiB缓冲区(bufferA和bufferB),每次写入大致分为8个写入 - bufferA1,bufferA2,...和bufferB1,bufferB2,... 如果bufferA4无法写入(由于负载太大或接收器错误地在回调中花费了太多时间),框架是否会破坏?那就是bufferA在接收端不正确地由bufferA1,bufferA2,bufferA3,bufferA5,bufferA6,bufferA7,bufferA8,bufferB1组成。
是否有任何关于不打破框架的保证。
2.我总是在NettyReceiveHandler :: decode中返回null,因为我没有任何上游处理程序吗?
感谢您的帮助。
答案 0 :(得分:2)
假设有TCP连接,那么您的大写不会被删除。 Netty会将数据排队,直到可以写入。通过引发INTEREST_OPS事件,Netty可能会发出写入队列已满的信号,但它不会阻止您排队更多数据。
就我个人而言,我会稍微处理一下。我不会扩展LengthFieldBasedFrameDecoder,而是创建一个包含2个处理程序的管道 - 标准的LengthFieldBasedFrameDecoder和NettyReceiveHandler。然后,您所要做的就是覆盖messageReceived并使用e.getMessage()(或任何您称为Message事件参数)调用您的侦听器。调用LengthFieldBasedFrameDecoder的解码方法,或者担心是否需要返回null,并没有搞乱。只需处理消息。