【Netty源码分析】数据读取过程
来源:互联网 发布:部落冲突vb.67.9破解版 编辑:程序博客网 时间:2024/06/05 08:57
首先客户端连接到服务端时服务端会开启一个线程,不断的监听客户端的操作。
这个线程的执行操作在NioEventLoop的run方法中,其实操作是在processSelectedKeys中,监听是否进行读操作
protected void run() { for (;;) { try { switch (selectStrategy.calculateStrategy(selectNowSupplier, hasTasks())) { case SelectStrategy.CONTINUE: continue; case SelectStrategy.SELECT: select(wakenUp.getAndSet(false)); if (wakenUp.get()) { selector.wakeup(); } default: // fallthrough } cancelledKeys = 0; needsToSelectAgain = false; final int ioRatio = this.ioRatio; if (ioRatio == 100) { processSelectedKeys(); runAllTasks(); } else { final long ioStartTime = System.nanoTime(); processSelectedKeys(); final long ioTime = System.nanoTime() - ioStartTime; runAllTasks(ioTime * (100 - ioRatio) / ioRatio); } if (isShuttingDown()) { closeAll(); if (confirmShutdown()) { break; } } } } }
private void processSelectedKeys() { if (selectedKeys != null) { processSelectedKeysOptimized(selectedKeys.flip()); } else { processSelectedKeysPlain(selector.selectedKeys()); } }判断selectedKeys数组中是否有值,其实就是read,write或accept事件
private void processSelectedKeysOptimized(SelectionKey[] selectedKeys) { for (int i = 0;; i ++) { final SelectionKey k = selectedKeys[i]; if (k == null) { break; } selectedKeys[i] = null; final Object a = k.attachment(); if (a instanceof AbstractNioChannel) { processSelectedKey(k, (AbstractNioChannel) a); } else { @SuppressWarnings("unchecked") NioTask<SelectableChannel> task = (NioTask<SelectableChannel>) a; processSelectedKey(k, task); } } }
主要判断int readyOps = k.readyOps();拿到的值是否是SelectionKey.OP_READ | SelectionKey.OP_ACCEPT
private void processSelectedKey(SelectionKey k, AbstractNioChannel ch) { final AbstractNioChannel.NioUnsafe unsafe = ch.unsafe(); if (!k.isValid()) { final EventLoop eventLoop; try { eventLoop = ch.eventLoop(); } catch (Throwable ignored) { } if (eventLoop != this || eventLoop == null) { return; } unsafe.close(unsafe.voidPromise()); return; } try { int readyOps = k.readyOps(); if ((readyOps & (SelectionKey.OP_READ | SelectionKey.OP_ACCEPT)) != 0 || readyOps == 0) { unsafe.read(); if (!ch.isOpen()) { return; } } if ((readyOps & SelectionKey.OP_WRITE) != 0) { ch.unsafe().forceFlush(); } if ((readyOps & SelectionKey.OP_CONNECT) != 0) { int ops = k.interestOps(); ops &= ~SelectionKey.OP_CONNECT; k.interestOps(ops); unsafe.finishConnect(); } } catch (CancelledKeyException ignored) { unsafe.close(unsafe.voidPromise()); } }
如果int readyOps = k.readyOps();拿到的值是SelectionKey.OP_READ | SelectionKey.OP_ACCEPT就执行unsafe.read();
具体实现在AbstractNioByteChannel执行read操作
@Overridepublic final void read() {final ChannelConfig config = config();final ChannelPipeline pipeline = pipeline();final ByteBufAllocator allocator = config.getAllocator();final RecvByteBufAllocator.Handle allocHandle = recvBufAllocHandle();allocHandle.reset(config);ByteBuf byteBuf = null;boolean close = false;try {do {byteBuf = allocHandle.allocate(allocator);allocHandle.lastBytesRead(doReadBytes(byteBuf));if (allocHandle.lastBytesRead() <= 0) {// nothing was read. release the buffer.byteBuf.release();byteBuf = null;close = allocHandle.lastBytesRead() < 0;break;}allocHandle.incMessagesRead(1);readPending = false;pipeline.fireChannelRead(byteBuf);byteBuf = null; } while (allocHandle.continueReading());allocHandle.readComplete();pipeline.fireChannelReadComplete();if (close) {closeOnRead(pipeline);}} catch (Throwable t) {handleReadException(pipeline, byteBuf, t, close, allocHandle);} }
读取操作是在doReadBytes(byteBuf)中,具体实现是在NioSocketChannel中
@Override protected int doReadBytes(ByteBuf byteBuf) throws Exception { final RecvByteBufAllocator.Handle allocHandle = unsafe().recvBufAllocHandle(); allocHandle.attemptedBytesRead(byteBuf.writableBytes()); return byteBuf.writeBytes(javaChannel(), allocHandle.attemptedBytesRead()); }接下来的操作是在AbstractByteBuf的writeBytes中进行。
@Override public int writeBytes(ScatteringByteChannel in, int length) throws IOException { ensureAccessible(); ensureWritable(length); int writtenBytes = setBytes(writerIndex, in, length); if (writtenBytes > 0) { writerIndex += writtenBytes; } return writtenBytes; }读取数据操作是在setBytes函数中进行的,一般实现是在PooledUnsafeDirectByteBuf类中
@Override public int setBytes(int index, ScatteringByteChannel in, int length) throws IOException { checkIndex(index, length); ByteBuffer tmpBuf = internalNioBuffer(); index = idx(index); tmpBuf.clear().position(index).limit(index + length); try { return in.read(tmpBuf); } catch (ClosedChannelException ignored) { return -1; } }在这里我们可以看到操作in.read(tmpBuf),这个操作就是NIO的读取数据操作了,in是SocketChannel对象,将数据读取到缓存中去,完成数据的读取过程。
0 0
- 【Netty源码分析】数据读取过程
- 【Netty源码分析】发送数据过程
- 【Netty源码分析】客户端connect服务端过程
- 【Netty源码分析】Netty服务端bind端口过程
- netty源码分析(十九)Netty项目开发过程中常见且重要事项分析
- Netty学习6-ChanelHandler【2】调用过程源码分析
- Netty启动过程分析
- Netty 源码分析
- netty源码分析小结
- netty 源码分析一
- netty 源码分析二
- netty源码分析
- Netty源码分析
- netty源码分析一
- 【Netty】源码分析目录
- Netty源码分析:NioEventLoopGroup
- Netty源码分析:ServerBootstrap
- Netty源码分析:ChannelPipeline
- secureCRT连接虚拟机与使用设置
- ListView或GridView上添加能一起滚动的Button效果的解决思路
- Java 8新特性探究(三):解开lambda最强作用的神秘面纱
- 队列和栈的应用 ------ 停车场
- java集合框架
- 【Netty源码分析】数据读取过程
- 更新npm和node版本
- spring 源码之二springmvc实现源码分析
- 简单测试连接mysql数据库
- 笔记同步到Github
- Java实现 RSA加密解密及数字签名
- Win7搭iis+asp+access的问题
- 微信公众平台开发环境搭建
- JavaMail详解