channelRead()和channelReadComplete() 方法的区别是什么?

我在看ChannelInboundHandler源码的时候,看到了这两个方法,英语注释,单词也都认识。但是还是没明白注释的意思?可以给我解释一下吗?
源码如下:

/**
 * Invoked when the current {@link Channel} has read a message from the peer.
 */
void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception;

/**
 * Invoked when the last message read by the current read operation has been consumed by
 * {@link #channelRead(ChannelHandlerContext, Object)}.  If {@link ChannelOption#AUTO_READ} is off, no further
 * attempt to read an inbound data from the current {@link Channel} will be made until
 * {@link ChannelHandlerContext#read()} is called.
 */
void channelReadComplete(ChannelHandlerContext ctx) throws Exception;
阅读 23.9k
2 个回答

楼上说的是对的,但是翻过来解释可能会更加容易理解。首先看下面这段代码,这个例子是Netty in action里的第二章里的例子,这个是Server的回调方法。

channelRead表示接收消息,可以看到msg转换成了ByteBuf,然后打印,也就是把Client传过来的消息打印了一下,你会发现每次打印完后,channelReadComplete也会调用,如果你试着传一个超长的字符串过来,超过1024个字母长度,你会发现channelRead会调用多次,而channelReadComplete只调用一次。

所以这就比较清晰了吧,因为ByteBuf是有长度限制的,所以超长了,就会多次读取,也就是调用多次channelRead,而channelReadComplete则是每条消息只会调用一次,无论你多长,分多少次读取,只在该条消息最后一次读取完成的时候调用,所以这段代码把关闭Channel的操作放在channelReadComplete里,放到channelRead里可能消息太长了,结果第一次读完就关掉连接了,后面的消息全丢了。

@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
    ByteBuf in = (ByteBuf) msg;
    //将消息记录到控制台
    System.out.println( "Server received: " + in.toString(CharsetUtil.UTF_8) + ",size is " + in.toString(CharsetUtil.UTF_8).length());
    ctx.write(in);
}

@Override
public void channelReadComplete(ChannelHandlerContext ctx) {
    System.out.println("channelReadComplete");
    ctx.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);
}

channel上面有数据到来时会触发channelRead事件,当数据到来时,eventLoop被唤醒继而调用channelRead方法处理数据。

channelReadComplete事件参考 How does netty determine when a read is complete?
大致意思是eventLoop被到来的数据唤醒后read数据并包装成msg,然后将msg作为参数调用channelRead方法,期间做个判断,read到0个字节或者是read到的字节数小于buffer的容量,满足以上条件就会调用channelReadComplete方法。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
宣传栏