我写了一个基于netty 4的REST服务器。客户端处理程序类似于以下内容。
netty提供的msg中的bytebuffer容量各不相同。当客户端消息大于缓冲区时,消息将被拆分。我发现每个片段都会调用channelRead和ChannelReadComplete。我通常看到的是ByteBuf大约是512,消息大约是600.我得到前512个字节的channelRead,接着是ChannelReadComplete,然后是剩下的100个字节的另一个channelRead和它们的channelReadComplete - 2条消息而不是1条。
我在这里找到了一些相关的问题,但我想知道channelReadComplete的重点是什么?它是否真的在每个channelRead之后调用?只要有可用的字节,在调用channelReadComplete之前不应该读入它们吗?
public class ClientHandler extends ChannelInboundHandlerAdapter {
....
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
Report.debug("Read from client");
ByteBuf buf = (ByteBuf) msg;
String contents = buf.toString(io.netty.util.CharsetUtil.US_ASCII);
ReferenceCountUtil.release(msg);
ClientConnection client = ClientConnection.get(ctx);
if (client != null) {
client.messageText(contents); // adds text to buffer
return;
}
((parse serial number from contents, process registration))
ClientConnection.online(serialNumber, ctx); // register success, create the client object
}
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
ClientConnection client = ClientConnection.get(ctx);
if (client == null)
Report.debug("completed read of message from unregistered client");
else {
Report.debug("completed read of message from client " + client.serialNumber());
String contents = client.messageText();
... ((process message))
}
}
}
答案 0 :(得分:1)
每个channelRead后都不会调用channelReadComplete。 netty事件循环将从NIO套接字读取并触发多个channelRead,直到没有更多数据要读或它应该放弃,然后触发channelReadComplete。
答案 1 :(得分:0)
是的,在管道中的每个channelRead()完成后调用channelReadComplete()。如果channelRead()中发生异常,那么它将跳转到ecxeptionCaught()方法。
所以你应该把代码放到你想要在成功的channelRead()上执行的channelReadComplete()中。
例如,这就是我们的项目:
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
// compute msg
ctx.fireChannelRead(msg); //tells the next handler
//in pipeline (if existing) to read the channel
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
ctx.writeAndFlush("OK");
ctx.fireChannelReadComplete();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
logger.error(Message.RCV_ERROR, cause.getMessage());
ctx.writeAndFlush(cause.getMessage());
ctx.close();
}
如果客户收到与“OK”不同的内容,则他不必发送其余内容。 如果您正在寻找一个在所有软件包到达后调用的方法:
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
//close the writer that wrote the message to file (for example)
}
编辑:你也可以尝试发送更大的包。我认为邮件大小由客户端控制。