网站首页 > 开源技术 正文
13.1 NIO
NIO,即非阻塞IO。关键点包括Channel, Selector。
Channel向Selector注册事件,如READ,WRITE,CONNECT。当Selector检测到channel上的相关事件发生时,会通知到应用程序。所谓非阻塞,也并非一点都不阻塞,只是阻塞点发生了变化。
13.2 Reactor
hprose用到一种称为Reactor模式的框架。
Reactor继承自Thread,运行在一个单独的线程里。
Reactor之上有个ReactorGroup,称为组。一个组可包括多个Reactor,即可以有多个独立运行的线程。
这样做的好处是,可以利用多核性质,提高系统性能。一个线程处理若干channel上的事件,各线程又独立运转,因此效率较高,但有时需要注意线程同步问题。
13.3 hprose客户端连接过程
hprose客户端连接服务器从Connector类开始
Connector构造时,生成一个Selector实例,生成一个ReactorGroup组实例,组中可容纳的线程数量由外部传入(reactorThreads变量)。
当外部调用Connector的start()方法时,线程就开始运转了。
run()方法会一直运行,直到线程被打断。在run方法的开始,调了ReactorGroup的start()方法,此时组的线程也开始运行。
当客户端试图连接服务器时,会调用哪个方法呢?会调下面的create方法,
这个方法内,通过SocketChannel.open()生成一个SocketChannel实例channel,并且将channel,handler(外部设置的连接回调),address封装到了一个新Connection实例中。同时配置channel为非阻塞。方法中有个register(conn)调用,
register方法只是简单的将conn置入队列queue中,然后唤醒selector, 为何要唤醒?
到这里,还没有发现是如何连接的。因为还没有见到channel.connect()类似这样的调用,这是连接的关键代码。
看来,连接要在run()循环中去找。
在run()方法中,有调用 process()方法
这个方法中,从queue中取出一个Conection实例,然后调conn.connect()方法,继续探究:
此处,channel向selector注册了事件 OP_CONNECT, 并且调用关键代码 channel.connect(address),到此终于看到客户端是如何连接的。
但调下channel.connect是不是完了呢?还没有。
还需要在Connector.dispatch()方法中,作处理
87行代码selector.select()其实是个阻塞方法,当没有检测到任何事件发生时,会一直阻塞。这就是之前调register()方法,将selector唤醒的原因。若不唤醒,线程可能会一直阻塞。看到这里,就知道NIO非阻塞,其实并不是一点也不阻塞,只是阻塞点发生了变化。但这样的一个变化,节约了程序的执行时间,程序不需要一遍遍轮询数据有没有准备好。
接下来的90-98行代码,是selector处理的一般写法。即获取一个迭代器,遍历,依次检测key的状态,调
it.remove()。
key.isConnectable()为true,说明已经检测到连接好了的事件。
连接好以后,调connect()方法
本方法中,通过调channel.finishConnect()完成连接过程。并且将这个conn注册到reactor中。
为什么要将conn注册到reactor中呢?因为conn虽然连接好了,但接下来需要通过conn发送数据,接收服务器传来的数据,这些操作事件的监听放到哪里去处理呢?可以放到Conector实例内,但这样做一个Connector需要完成多件事,会使效率变慢。所以放到了reactor这样专门处理读写的线程内,reactor其实是一个组实例,在组内,又可以将conn分到不同的线程内,进一步提高执行效率。
到此,完成了连接过程。但是,应用程序又怎么知道连接完成了,因为应用程序知道连接完成以后,就要开始发送数据了。这就是连接回调设置的目的。
猜你喜欢
- 2024-10-30 常见的Socket网络异常场景分析(socket异常连接怎么重置)
- 2024-10-30 JVM性能调优监控工具jps、jstack、jmap、jhat、hprof使用详解
- 2024-10-30 一文读懂CPU的层次结构(cpu的结构与原理)
- 2024-10-30 网络安全学习(5) - hping3 学习(hunter网络安全)
- 2024-10-30 一文读懂如何查看网络的性能指标(如何查看网络强度)
- 2024-10-30 如何使用网上公开的exp(如何使用网上邻居)
- 2024-10-30 C++ Socket 编程(c++ socket教程)
- 2024-10-30 FM2+ APU 最后逆袭,搭载 USB3.1 技嘉 F2A88XM-D3HP
- 2024-10-30 hprose for java源码分析-16 服务器启动
- 2024-10-30 得力DM34ADN国产打印机在银河麒麟系统上安装和设置的方法
你 发表评论:
欢迎- 最近发表
-
- 6月游戏推荐(二)(6月份新出的游戏)
- 37【源码】数据可视化:基于 Echarts + Python 动态实时大屏
- Kubernetes Kube-Proxy 组件 IPVS 模式工作原理及常用故障排查
- 《茶余饭后顶级英文歌曲精选》(茶余饭后的经典句子)
- rainx和MediaTek携手推出101产品生态,为5G FWA提供创新
- KAPITAL 推出蓝染风格 Aloha Shirt 系列
- 欧美经典怀旧歌曲Free loop-管不住的音符
- Mac 下php5.3-7.0的二进制包 ── PHP-OS
- 如何把一个Python应用程序装进Docker
- 为何推荐 JsonTree.js 做 JSON 可视化?
- 标签列表
-
- jdk (81)
- putty (66)
- rufus (78)
- 内网穿透 (89)
- okhttp (70)
- powertoys (74)
- windowsterminal (81)
- netcat (65)
- ghostscript (65)
- veracrypt (65)
- asp.netcore (70)
- wrk (67)
- aspose.words (80)
- itk (80)
- ajaxfileupload.js (66)
- sqlhelper (67)
- express.js (67)
- phpmailer (67)
- xjar (70)
- redisclient (78)
- wakeonlan (66)
- tinygo (85)
- startbbs (72)
- webftp (82)
- vsvim (79)
本文暂时没有评论,来添加一个吧(●'◡'●)