Netty中的永动机

永动机即'永远运动的机器'.

作为服务端时, 需要接收客户端的连接, 需要接收客户端的数据, 或者向客户端发送数据.

既然需要接收客户端的连接, 那么就需要一个IO线程永远的执行一个无限循环.只有一直循环着, 才能一直接收新的连接.

NioEventLoop的底层绑定一个线程, 这个线程在启动之后, 就会一直无限循环着, 而且只做三件事

1.轮询IO事件

2.处理IO事件

3.执行任务

当有新的客户端连接到服务端的时候(TCP三次握手已经完成), 服务端的IO线程就会轮询到有客户端的连接****事件. 接下来就会处理这个连接事件.

IO线程会创建一个针对这个客户端与之对应的NioSocketChannel, 然后把这个Channel注册到另一类NioEventLoop(它的底层也会绑定一个线程)上.

从图中可以看出, 右侧的IO线程只会负责读写事件, 并不会负责连接事件.

当客户端给服务端发送数据的时候, 服务端IO线程轮询到读事件, 接下来就会处理这个读事件. 会读取到客户端发送过来的数据, 经过解码器解码, 再把数据传给业务Handler进行处理.

然而一般情况下, 当服务端需要向客户端写数据的时候, 直接调用相应的函数(writeAndFlush)即可, 并不会涉及到写事件. 那么什么时候才会涉及到写事件呢? 当网络出现拥堵的情况, 或者客户端没有及时处理服务端发给它的数据. 那么服务端的Socket的TCP缓冲区就会被写满, 这个时候再向缓冲区写数据就会失败, Netty就会注册一个写事件. 当TCP缓冲区可写的时候, Netty就会继续将之前没有写完的数据,再次向TCP缓冲区写.

如果把Netty的服务端比作一台大型的机器. 那么在这个机器里, 有好几个一直运作地大齿轮(每个NioEventLoop就是一个大齿轮). 这些大齿轮一直转着,一直转着, 从不停止.

以上说了服务端的三个IO事件, 分别是连接事件, 读事件, 写事件. 准确的说应该是接收连接事件, 读事件, 写事件.

因为在客户端也有三个IO事件, 分别是连接事件, 读事件, 写事件. 如下图

如上图右侧所示, 客户端轮询着连接事件, 读事件和写事件. 读写事件和服务端一样, 说一下连接事件.

Netty在进行TCP三次握手的时候, 由于网络等原因, Netty并没有一直等待着连接完成, 客户端在发起连接之后, 便注册了一个连接事件. 当TCP三次握手完成之后, IO线程轮询到了连接完成事件. 接下来就会做一些连接完成的后续工作, 同时取消连接事件. 关键代码如下

1// 源码位置: io.netty.channel.socket.nio.NioSocketChannel#doConnect 2 3 4 5// 源码位置: io.netty.channel.nio.NioEventLoop#processSelectedKey(java.nio.channels.SelectionKey, io.netty.channel.nio.AbstractNioChannel)

总结: 此篇文件简单说了下Netty作为服务端和客户端的时候, IO线程一直在无限循环着, 傻傻地做着轮询IO事件, 处理IO事件, 执行任务这三件事.

本文分享自微信公众号 - Netty历险记(infuq217)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

Netty面试

Netty面试1.BIO、NIO和AIO的区别?BIO:tex一个连接一个线程,客户端有连接请求时服务器端就需要启动一个线程进行处理。线程开销大。伪异步IO:将请求连接放入线程池,一对多,但线程还是很宝贵的资源

Netty面试题

1.BIO、NIO和AIO的区别?BIO:一个连接一个线程,客户端有连接请求时服务器端就需要启动一个线程进行处理。线程开销大。伪异步IO:将请求连接放入线程池,一对多,但线程还是很宝贵的资源。NIO:一个请求一个线程,但客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处