Netty 4 的 Channel 多了一个 autoread 参数, 它的用处是在让 channel 在触发某些事件以后(例如 channelActive, channelReadComplete)以后还会自动调用一次 read(), 代码:

DefaultChannelPipeline.java

  1. @Override
  2. public ChannelPipeline fireChannelActive() {
  3. head.fireChannelActive();
  4.  
  5. if (channel.config().isAutoRead()) {
  6. channel.read();
  7. }
  8.  
  9. return this;
  10. }
  11.  
  12. -----------------------------------
  13.  
  14. @Override
  15. public ChannelPipeline fireChannelReadComplete() {
  16. head.fireChannelReadComplete();
  17. if (channel.config().isAutoRead()) {
  18. read();
  19. }
  20. return this;
  21. }

另外一个很重要的作用是在触发某些事件(例如 socket 关闭)时, 在 NioEventloop 的 OP_READ 位为 1 时, 是否真正的去 channel 读取数据, 去 channel 读取数据的意义还包括可以更新 channel 的状态, 例如改变 active 状态等, 代码:

Eventloop.java

  1. private static void processSelectedKey(SelectionKey k, AbstractNioChannel ch) {
  2. final NioUnsafe unsafe = ch.unsafe();
  3. if (!k.isValid()) {
  4. // close the channel if the key is not valid anymore
  5. unsafe.close(unsafe.voidPromise());
  6. return;
  7. }
  8.  
  9. try {
  10. int readyOps = k.readyOps();
  11. // Also check for readOps of 0 to workaround possible JDK bug which may otherwise lead
  12. // to a spin loop
  13. if ((readyOps & (SelectionKey.OP_READ | SelectionKey.OP_ACCEPT)) != 0 || readyOps == 0) {
  14. unsafe.read();
  15. if (!ch.isOpen()) {
  16. // Connection already closed - no need to handle write.
  17. return;
  18. }
  19. }
  20. if ((readyOps & SelectionKey.OP_WRITE) != 0) {
  21. // Call forceFlush which will also take care of clear the OP_WRITE once there is nothing left to write
  22. ch.unsafe().forceFlush();
  23. }
  24. if ((readyOps & SelectionKey.OP_CONNECT) != 0) {
  25. // remove OP_CONNECT as otherwise Selector.select(..) will always return without blocking
  26. // See https://github.com/netty/netty/issues/924
  27. int ops = k.interestOps();
  28. ops &= ~SelectionKey.OP_CONNECT;
  29. k.interestOps(ops);
  30.  
  31. unsafe.finishConnect();
  32. }
  33. } catch (CancelledKeyException e) {
  34. unsafe.close(unsafe.voidPromise());
  35. }
  36. }

AbstractNioByteChannel.java (unsafe.read())

  1. public void read() {
  2. final ChannelConfig config = config();
    // 判断是否是 autoread, 如果不是直接移除 opRead 标志位返回
  3. if (!config.isAutoRead() && !isReadPending()) {
  4. // ChannelConfig.setAutoRead(false) was called in the meantime
  5. removeReadOp();
  6. return;
  7. }
  8. final ChannelPipeline pipeline = pipeline();
  9. final ByteBufAllocator allocator = config.getAllocator();
  10. final int maxMessagesPerRead = config.getMaxMessagesPerRead();
  11. RecvByteBufAllocator.Handle allocHandle = this.allocHandle;
  12. if (allocHandle == null) {
  13. this.allocHandle = allocHandle = config.getRecvByteBufAllocator().newHandle();
  14. }
  15. ByteBuf byteBuf = null;
  16. int messages = 0;
  17. boolean close = false;
  18. try {
  19. int totalReadAmount = 0;
  20. boolean readPendingReset = false;
  21. do {
  22. byteBuf = allocHandle.allocate(allocator);
  23. int writable = byteBuf.writableBytes();
    // 这里会到 channel 中 read 一次, 如果返回 -1, 则表示 channel 关闭
    // 假如说 autoread 为 false, 则在 socket close 时永远不会进入这里, 从而改变 channel 的 active 状态
  24. int localReadAmount = doReadBytes(byteBuf);
  25. if (localReadAmount <= 0) {
  26. // not was read release the buffer
  27. byteBuf.release();
  28. close = localReadAmount < 0;
  29. break;
  30. }
  31. if (!readPendingReset) {
  32. readPendingReset = true;
  33. setReadPending(false);
  34. }
  35. pipeline.fireChannelRead(byteBuf);
  36. byteBuf = null;
  37. if (totalReadAmount >= Integer.MAX_VALUE - localReadAmount) {
  38. // Avoid overflow.
  39. totalReadAmount = Integer.MAX_VALUE;
  40. break;
  41. }
  42. totalReadAmount += localReadAmount;
  43. // stop reading
  44. if (!config.isAutoRead()) {
  45. break;
  46. }
  47. if (localReadAmount < writable) {
  48. // Read less than what the buffer can hold,
  49. // which might mean we drained the recv buffer completely.
  50. break;
  51. }
  52. } while (++ messages < maxMessagesPerRead);
  53. pipeline.fireChannelReadComplete();
  54. allocHandle.record(totalReadAmount);
  55. // 关闭 channel, 并改变 channel active 状态
  56. if (close) {
  57. closeOnRead(pipeline);
  58. close = false;
  59. }
  60. } catch (Throwable t) {
  61. handleReadException(pipeline, byteBuf, t, close);
  62. } finally {
  63. // Check if there is a readPending which was not processed yet.
  64. // This could be for two reasons:
  65. // * The user called Channel.read() or ChannelHandlerContext.read() in channelRead(...) method
  66. // * The user called Channel.read() or ChannelHandlerContext.read() in channelReadComplete(...) method
  67. //
  68. // See https://github.com/netty/netty/issues/2254
  69. if (!config.isAutoRead() && !isReadPending()) {
  70. removeReadOp();
  71. }
  72. }
  73. }
  74. }

关于 Netty Channel 的 Autoread的更多相关文章

  1. SparkStreaming+Flume出现ERROR ReceiverTracker: Deregistered receiver for stream 0: Error starting receiver 0 - org.jboss.netty.channel.ChannelException

    文章发自http://www.cnblogs.com/hark0623/p/4204104.html ,转载请注明 我发现太多太多的坑要趟了… 向yarn提交sparkstreaming了,提交脚本如 ...

  2. android netty5.0 编译时 java.lang.NoClassDefFoundError: io.netty.channel.nio.NioEventLoopGroup

    android netty5.0 编译时 java.lang.NoClassDefFoundError: io.netty.channel.nio.NioEventLoopGroup 复制netty包 ...

  3. netty-websocket-spring-boot-starter关闭报错 io/netty/channel/AbstractChannel$AbstractUnsafe io/netty/util/concurrent/GlobalEventExecutor

    报错 java.lang.NoClassDefFoundError: io/netty/channel/AbstractChannel$AbstractUnsafe$ at io.netty.chan ...

  4. Netty Channel 接口名词理解

    1.Channel channel 是负责数据读,写的对象,有点类似于老的io里面的stream.它和stream的区别,channel是双向的,既可以write 也可以read,而stream要分o ...

  5. netty源码解解析(4.0)-3 Channel的抽象实现

    AbstractChannel和AbstractUnsafe抽象类 io.netty.channel.AbstractChannel 从本章开始,会有大量的篇幅涉及到代码分析.为了能够清晰简洁的地说明 ...

  6. Netty那点事: 概述, Netty中的buffer, Channel与Pipeline

    Netty那点事(一)概述 Netty和Mina是Java世界非常知名的通讯框架.它们都出自同一个作者,Mina诞生略早,属于Apache基金会,而Netty开始在Jboss名下,后来出来自立门户ne ...

  7. [编织消息框架][netty源码分析]8 Channel 实现类NioSocketChannel职责与实现

    Unsafe是托委访问socket,那么Channel是直接提供给开发者使用的 Channel 主要有两个实现 NioServerSocketChannel同NioSocketChannel 致于其它 ...

  8. netty源码解解析(4.0)-14 Channel NIO实现:读取数据

     本章分析Nio Channel的数据读取功能的实现. Channel读取数据需要Channel和ChannelHandler配合使用,netty设计数据读取功能包括三个要素:Channel, Eve ...

  9. netty源码解解析(4.0)-15 Channel NIO实现:写数据

    写数据是NIO Channel实现的另一个比较复杂的功能.每一个channel都有一个outboundBuffer,这是一个输出缓冲区.当调用channel的write方法写数据时,这个数据被一系列C ...

随机推荐

  1. cut命令

    cut是一个选取命令,就是将一段数据经过分析,取出我们想要的.一般来说,选取信息通常是针对"行"来进行分析的,并不是整篇信息分析的. (1)其语法格式为:cut  [-bn] [f ...

  2. 拒绝访问 temp 目录。用来运行 XmlSerializer 的标识“IIS APPPOOL\UGAS”没有访问 temp 目录的足够权限

    在部署IIS时候会出现下图错误,拒绝访问 temp 目录.用来运行 XmlSerializer 的标识“IIS APPPOOL\UGAS”没有访问 temp 目录的足够权限 解决方法: 在IIS信息管 ...

  3. 百度云 + GIT

    百度云同步 百度云同步,会将本地的某个文件目录和云端进行同步.如果在本地将这个同步的目录设置为Git的中心服务器,那么本地push到中心服务器的内容也会被同步到云端.其他开发者只要也进行相同的设置,就 ...

  4. Maximo-获取url

    //访问报表public void OPENREPORT() throws RemoteException, MXException{ int polineid=this.getMbo().getIn ...

  5. vs2012安装Microsoft.AspNet.WebApi.WebHost

    工具---库程序包管理器---程序包管理器控制台:输入下面命令:  Install-Package Microsoft.AspNet.WebApi.WebHost 

  6. <读书笔记> 代码整洁之道

    概述      1.本文档的内容主要来源于书籍<代码整洁之道>作者Robert C.Martin,属于读书笔记. 2.软件质量,不仅依赖于架构和项目管理,而且与代码质量紧密相关,本书提出一 ...

  7. C语言编程技巧-signal(信号)[转]

    自 http://www.uml.org.cn/c++/200812083.asp 信号是Linux编程中非常重要的部分,本文将详细介绍信号机制的基本概念.Linux对信号机制的大致实现方法.如何使用 ...

  8. thinkphp修改及编写标签库,编辑器的使用

    在view目录下创建Index_aaa.html <!DOCTYPE html> <html> <head> <meta charset="UTF- ...

  9. MSSQL 查询数据库所有表的大小, 有助于删除一些没用的表

    SELECT b.name AS tablename , a.rowcnt AS datacount FROM sysindexes a , sysobjects b WHERE a.id = b.i ...

  10. MongoDB是一个介于关系数据库和非关系数据库之间的产品

    MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的.他支持的数据结构非常松散,是类似json的bjson格式,因此可以存储比较复杂的数据类型.M ...