• netty-read


    NioEventLoop是ServerSocketChannel和SocketChannel通用的EventLoop,从NioEventLoop的执行逻辑开始

     1 protected void run() {
     2   for (;;) {
     3     switch (selectStrategy.calculateStrategy(selectNowSupplier, hasTasks())) {
     4       case SelectStrategy.CONTINUE:
     5         continue;
     6       case SelectStrategy.SELECT:
     7         select(wakenUp.getAndSet(false));
     8         if (wakenUp.get()) {
     9           selector.wakeup();
    10         }
    11       default:
    12         // fallthrough
    13     }
    14 
    15     cancelledKeys = 0;
    16     needsToSelectAgain = false;
    17     final int ioRatio = this.ioRatio;
    18     if (ioRatio == 100) {
    19       try {
    20         //处理IO事件
    21         processSelectedKeys();
    22       } finally {
    23         // Ensure we always run tasks.
    24         //处理队列中任务
    25         runAllTasks();
    26       }
    27     } else {
    28       final long ioStartTime = System.nanoTime();
    29       try {
    30         processSelectedKeys();
    31       } finally {
    32         // Ensure we always run tasks.
    33         final long ioTime = System.nanoTime() - ioStartTime;
    34         runAllTasks(ioTime * (100 - ioRatio) / ioRatio);
    35       }
    36     }
    37   }
    38 }
     1 //eventLoop持有selector,可以得到selectedKeys
     2 private void processSelectedKeysPlain(Set<SelectionKey> selectedKeys) {
     3 
     4   if (selectedKeys.isEmpty()) {
     5     return;
     6   }
     7 
     8   Iterator<SelectionKey> i = selectedKeys.iterator();
     9   for (;;) {
    10     final SelectionKey k = i.next();
    11     //java.nio.channels.ServerSocketChannel的attachment是io.netty.channel.socket.ServerSocketChannel,
    12     //java.nio.channels.SocketChannel的attachment是io.netty.channel.socket.SocketChannel,
    13     final Object a = k.attachment();
    14     i.remove();
    15 
    16     if (a instanceof AbstractNioChannel) {
    17       processSelectedKey(k, (AbstractNioChannel) a);
    18     } else {
    19       @SuppressWarnings("unchecked")
    20       NioTask<SelectableChannel> task = (NioTask<SelectableChannel>) a;
    21       processSelectedKey(k, task);
    22     }
    23 
    24     if (!i.hasNext()) {
    25       break;
    26     }
    27 
    28     if (needsToSelectAgain) {
    29       selectAgain();
    30       selectedKeys = selector.selectedKeys();
    31 
    32       // Create the iterator again to avoid ConcurrentModificationException
    33       if (selectedKeys.isEmpty()) {
    34         break;
    35       } else {
    36         i = selectedKeys.iterator();
    37       }
    38     }
    39   }
    40 }
     1 //涵盖了SelectionKey.OP_CONNECT、SelectionKey.OP_WRITE、SelectionKey.OP_READ、SelectionKey.OP_ACCEPT四种事件
     2 private void processSelectedKey(SelectionKey k, AbstractNioChannel ch) {
     3   final AbstractNioChannel.NioUnsafe unsafe = ch.unsafe();
     4 
     5   int readyOps = k.readyOps();
     6 
     7   if ((readyOps & SelectionKey.OP_CONNECT) != 0) {
     8     int ops = k.interestOps();
     9     ops &= ~SelectionKey.OP_CONNECT;
    10     k.interestOps(ops);
    11 
    12     unsafe.finishConnect();
    13   }
    14 
    15   if ((readyOps & SelectionKey.OP_WRITE) != 0) {
    16     ch.unsafe().forceFlush();
    17   }
    18   if ((readyOps & (SelectionKey.OP_READ | SelectionKey.OP_ACCEPT)) != 0 || readyOps == 0) {
    19       //重点关注    
    20     unsafe.read();
    21   }
    22 }

    下面分别对NioMessageUnsafe以及NioByteUnsafe的read操作进行分析

    NioMessageUnsafe用于ServerSocketChannel,读取的是SocketChannel对象

     1 private final class NioMessageUnsafe extends AbstractNioUnsafe {
     2     //......
     3     
     4     public void read() {
     5       assert eventLoop().inEventLoop();
     6       final ChannelConfig config = config();
     7       final ChannelPipeline pipeline = pipeline();
     8       final RecvByteBufAllocator.Handle allocHandle = unsafe().recvBufAllocHandle();
     9       allocHandle.reset(config);
    10 
    11       boolean closed = false;
    12       Throwable exception = null;
    13 
    14       try {
    15         do {
    16             //真正的读取操作
    17           int localRead = doReadMessages(readBuf);
    18           //读完了
    19           if (localRead == 0) {
    20             break;
    21           }
    22           //localRead<0说明对端关闭了
    23           if (localRead < 0) {
    24             closed = true;
    25             break;
    26           }
    27 
    28           allocHandle.incMessagesRead(localRead);
    29         } while (allocHandle.continueReading());
    30       } catch (Throwable t) {
    31         exception = t;
    32       }
    33 
    34       int size = readBuf.size();
    35       for (int i = 0; i < size; i ++) {
    36         readPending = false;
    37         //发送给Handler处理,即回调Handler的channelRead。
    38         //对于serverSocketChannel来说,readBuf中装的是SocketChannel,
    39         //fireChannelRead就是发送给ServerBootstrapAcceptor,由ServerBootstrapAcceptor注册SocketChannel
    40         pipeline.fireChannelRead(readBuf.get(i));
    41       }
    42       readBuf.clear();
    43       allocHandle.readComplete();
    44       //回调Handler的channelReadComplete
    45       pipeline.fireChannelReadComplete();
    46 
    47       if (exception != null) {
    48         closed = closeOnReadError(exception);
    49             //回调Handler的ExceptionCaught
    50         pipeline.fireExceptionCaught(exception);
    51       }
    52 
    53       if (closed) {
    54         inputShutdown = true;
    55         if (isOpen()) {
    56             close(voidPromise());
    57         }
    58       }
    59     }
    60     
    61     //......
    62 }
     1 protected int doReadMessages(List<Object> buf) throws Exception {
     2     //调用java.nio.channels.ServerSocketChannel.accept()
     3   SocketChannel ch = SocketUtils.accept(javaChannel());
     4 
     5   try {
     6     if (ch != null) {
     7       buf.add(new NioSocketChannel(this, ch));
     8       return 1;
     9     }
    10   } catch (Throwable t) {
    11     try {
    12       ch.close();
    13     } catch (Throwable t2) {
    14       logger.warn("Failed to close a socket.", t2);
    15     }
    16   }
    17   return 0;
    18 }

    NioByteUnsafe用于SocketChannel,读取的是字节序列

     1 protected class NioByteUnsafe extends AbstractNioUnsafe {
     2     //......
     3     public final void read() {
     4       final ChannelConfig config = config();
     5       final ChannelPipeline pipeline = pipeline();
     6       final ByteBufAllocator allocator = config.getAllocator();
     7       final RecvByteBufAllocator.Handle allocHandle = recvBufAllocHandle();
     8       allocHandle.reset(config);
     9 
    10       ByteBuf byteBuf = null;
    11       boolean close = false;
    12       try {
    13         do {
    14             //每次读取都重新分配Buffer
    15           byteBuf = allocHandle.allocate(allocator);
    16           //真正的读取操作
    17           allocHandle.lastBytesRead(doReadBytes(byteBuf));
    18           //读到0表示数据读完,-1表示对端已关闭
    19           if (allocHandle.lastBytesRead() <= 0) {
    20             // nothing was read. release the buffer.
    21             byteBuf.release();
    22             byteBuf = null;
    23             //读到-1,表示对端已关闭
    24             close = allocHandle.lastBytesRead() < 0;
    25             break;
    26           }
    27 
    28           allocHandle.incMessagesRead(1);
    29           readPending = false;
    30           //将读取到的数据发送给Handler,即回调Handler的ChannelRead
    31           pipeline.fireChannelRead(byteBuf);
    32           byteBuf = null;
    33         } while (allocHandle.continueReading());
    34             
    35         allocHandle.readComplete();
    36         //回调Handler的ChannelReadComplete
    37         pipeline.fireChannelReadComplete();
    38 
    39         if (close) {
    40           closeOnRead(pipeline);
    41         }
    42       } catch (Throwable t) {
    43         handleReadException(pipeline, byteBuf, t, close, allocHandle);//会调用pipeline.fireChannelReadComplete和pipeline.fireExceptionCaught
    44       }
    45     }
    46     //......
    47 }
    1 protected int doReadBytes(ByteBuf byteBuf) throws Exception {
    2   final RecvByteBufAllocator.Handle allocHandle = unsafe().recvBufAllocHandle();
    3   allocHandle.attemptedBytesRead(byteBuf.writableBytes());
    4   //从java.nio.channels.SocketChannel中读取allocHandle.attemptedBytesRead()个字节置byteBuf中
    5   return byteBuf.writeBytes(javaChannel(), allocHandle.attemptedBytesRead());
    6 }
  • 相关阅读:
    判断一个值是不是数字
    webpack起的项目怎么用手机访问?
    vue 父子组件数据双向绑定
    js取整
    封装加减乘除函数 解决JS 浮点数计算 Bug
    javascript笔记 (持续更新)
    ajax请求的原生js实现
    程序员の健康和效率装备列表,普通人也能参考
    Java static,final 基本概念
    Download EditPlus Text Editor
  • 原文地址:https://www.cnblogs.com/holoyong/p/7436612.html
Copyright © 2020-2023  润新知