|
服务端: 服务端启动程序:
- package nio;
- /**
- * 服务端启动程序
- */
- public class ServerMain {
- public static void main (String[] args) {
- int port = 8010;
- ServerSocketChannels server = new ServerSocketChannels(port);
- new Thread(server, "timeserver-001").start();
- }
- }
|
客户端程序:
客户端启动程序:
- package nio;
- /**
- * 客户端启动程序
- */
- public class ClientMain {
- public static void main (String[] args) {
- int port = 8010;
- TimeClientHandler client = new TimeClientHandler( "",port);
- new Thread(client, "client-001").start();
- }
- }
|
现在说一下nio的执行过程:
第一步:启动server服务器,初始化多路复用器selector、ServerSocketChannel通道、设置通道的模式为非阻塞、注册channel到selector上,并监听accept请求;
第二步:启动server服务器,循环selectionKeys,当有channel准备好时就处理,否则一直循环;
第三步:启动client端,初始化多路复用器selector、SocketChannel通道,设置通道的模式为非阻塞;
第四步:client首先尝试连接server,此时socketChannel.connect(new InetSocketAddress(this.host, this.port)返回false,表示server还没有返回信息,server收到连接请求后,监听到client的接入请求,会初始化一个新的client、并将新接入的client注册到多路复用器Selector上,并应答client;再回到client端,由于client没有及时收到server端的应答,所以client胡监听一个connect请求,socketChannel.register(selector, SelectionKey.OP_CONNECT),当server返回应答信息时,client会收到一个connect请求,key.isConnectable(),如果此时sc.finishConnect()连接完成,client会监听一个read请求,并像server发送数据doWrite(sc),然后server会收到一个read请求,key.isReadable()处理完后返回给client,client也会收到一个读请求,收到server的返回数据,此时,整个交互过程结束;
截取一下书上的步骤:来自netty权威指南:
nio的优点:
1、客户端发起的连接操作connect是异步的,可以通过在多路复用器selector上监听connect事件等待后续结果,不需要像之前的客户端那样被同步阻塞;
2、SocketChannel的读写操作都是异步的,如果没有可读写的数据它不会同步等待,直接返回,这样IO线程就可以处理其它的链路,不需要同步等待这个链路可用;
3、线程模型的优化,由于jdk的selector在linux等主流操作系统上通过epoll实现,它没有连接句柄数的限制(只受限与操作系统的最大句柄数或者单个进程的句柄限制),这意味这一个selector可以连接成千上万个客户端连接,而性能不会随着客户端连接数的增长呈线性下降,因此,它适合做高性能、高负载的网络服务器;
----------------------------
原文链接:https://blog.csdn.net/chengkui1990/article/details/81558522
程序猿的技术大观园:www.javathinker.net
[这个贴子最后由 flybird 在 2020-02-07 10:54:24 重新编辑]
|
|