Java 被netty拆分的套接字消息

Java 被netty拆分的套接字消息,java,netty,Java,Netty,我基于Netty4编写了一个REST服务器。客户端处理程序如下所示 netty提供的msg中的bytebuffer容量各不相同。当客户端消息大于缓冲区时,消息将被拆分。我发现每个片段都会调用channelRead和ChannelReadComplete。我通常看到的是ByteBuf大约是512,消息大约是600。我得到了前512个字节的channelRead,然后是ChannelReadComplete,然后是另一个channelRead,用于剩下的100个字节,还有一个ChannelReadC

我基于Netty4编写了一个REST服务器。客户端处理程序如下所示

netty提供的msg中的bytebuffer容量各不相同。当客户端消息大于缓冲区时,消息将被拆分。我发现每个片段都会调用channelRead和ChannelReadComplete。我通常看到的是ByteBuf大约是512,消息大约是600。我得到了前512个字节的channelRead,然后是ChannelReadComplete,然后是另一个channelRead,用于剩下的100个字节,还有一个ChannelReadComplete-2条消息,而不是1条

我在这里发现了一些相关的问题,但我想知道channelReadComplete的意义是什么?它真的是在每次通灵阅读后被调用的吗?只要有可用的字节,就不应该在调用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))
        }
    }
 }
是的,在管道中的每个channelRead()完成后调用channelReadComplete()。如果channelRead()中发生异常,则它将跳转到方法ecxeptionCaught()

因此,您应该将代码放入channelReadComplete()中,您只希望在成功的channelRead()上执行这些代码

例如,我们的项目就是这样做的:

@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)
}

编辑:你也可以尝试发送更大的包。我认为,消息大小由客户端控制。

在每次channelRead之后都不会调用channelReadComplete。netty事件循环将从NIO套接字读取并触发多个channelRead,直到不再需要读取数据或应该放弃,然后触发channelReadComplete