这里实际上是注册感兴趣的事件,服务端到这里基本上已经告一段落了 。
客户端接入源码分析下面我们看一下 NioEventLoop 是如何处理客户端请求的 。
当多路复用器就绪时,默认执行 processSelectedKeysOptimized() 方法:
private void processSelectedKeysOptimized() { for (int i = 0; i < selectedKeys.size; ++i) { final SelectionKey k = selectedKeys.keys[i]; selectedKeys.keys[i] = null; final Object a = k.attachment(); // 这里处理的 attachment 是 AbstractNioChannel if (a instanceof AbstractNioChannel) { processSelectedKey(k, (AbstractNioChannel) a); } else { @SuppressWarnings("unchecked") NioTask<SelectableChannel> task = (NioTask<SelectableChannel>) a; processSelectedKey(k, task); } if (needsToSelectAgain) { // null out entries in the array to allow to have it GC'ed once the Channel close // See https://github.com/netty/netty/issues/2363 selectedKeys.reset(i + 1); selectAgain(); i = -1; } }}
这里实际上是根据不同的的类型,执行不同的操作:
private void processSelectedKey(SelectionKey k, AbstractNioChannel ch) { final AbstractNioChannel.NioUnsafe unsafe = ch.unsafe(); // 省略 try { int readyOps = k.readyOps(); if ((readyOps & SelectionKey.OP_CONNECT) != 0) { int ops = k.interestOps(); ops &= ~SelectionKey.OP_CONNECT; k.interestOps(ops); unsafe.finishConnect(); } // Process OP_WRITE first as we may be able to write some queued buffers and so free memory. if ((readyOps & SelectionKey.OP_WRITE) != 0) { // Call forceFlush which will also take care of clear the OP_WRITE once there is nothing left to write ch.unsafe().forceFlush(); } // Also check for readOps of 0 to workaround possible JDK bug which may otherwise lead // to a spin loop if ((readyOps & (SelectionKey.OP_READ | SelectionKey.OP_ACCEPT)) != 0 || readyOps == 0) { unsafe.read(); } } catch (CancelledKeyException ignored) { unsafe.close(unsafe.voidPromise()); } }
推荐阅读
- Netty 实战:如何实现文件服务器?
- Netty 实战:如何实现 HTTP 服务器?
- 什么是2021年最佳的后端开发框架
- 如何实现几百台SIP终端实现自动化部署
- 如何在 Linux 终端查看图像
- 浅谈linux下基于UDP服务的负载均衡方法
- 粽子是端午节的必备食物据说在春秋时期 关于端午粽子的由来
- 端午节五彩线的颜色 端午节绑五色线的意义
- 驱五毒是什么节日 端午节的五毒有哪些
- 课后服务申请理由怎么写?