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

发布于 2022-09-11 18:59:10 字数 693 浏览 15 评论 0

我在看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;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

清风挽心 2022-09-18 18:59:10

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

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

π浅易 2022-09-18 18:59:10

楼上说的是对的,但是翻过来解释可能会更加容易理解。首先看下面这段代码,这个例子是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);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文