Netty学习第六节实例一步学习

NIO与传统IO对应使用的类:
ServerSocketChannel至关于ServerSocket
SocketChannel 至关于Socket
Selector是NIO的核心类,是负责监听ServerSocketChannel和SocketChannel 
(因此NIO是能够实现单线程为多个客户端服务的,而传统IO是不能够的)
SelectionKey 返回的监听结果
 
原理实例解析:
好比若是餐厅是一个系统的话,serverSocket至关于一个餐厅的大门,只负责大门的看护(监视),也就是监听端口,客人就是socket,全部客人都须要经过大门进入餐厅,餐厅的服务员就至关于一个线程,传统socket是一个如图的模型(一个服务员服务一个客人):
 

 

 
若是NIO也是以一个餐厅系统,它的大门就是ServerSocketChannel ,客户端就是SocketChannel,服务员就是(线程+Selector),其服务员增长了selector能力,即为多个客户服务的能力,同时能够监听大门(欢迎新的客人),如图所示:
 
Selector.select()============没法看到源码,底层是基于C实现的.
实例代码:
 1 package com.NIO;  2 
 3 import java.io.IOException;  4 import java.net.InetSocketAddress;  5 import java.nio.ByteBuffer;  6 import java.nio.channels.SelectionKey;  7 import java.nio.channels.Selector;  8 import java.nio.channels.ServerSocketChannel;  9 import java.nio.channels.SocketChannel;  10 import java.util.Iterator;  11 
 12 /**
 13  * NIO服务端  14  *  15  * @author -琴兽-  16  */
 17 public class NIOServer {  18     // 通道管理器
 19     private Selector selector;  20 
 21     /**
 22  * 得到一个ServerSocket通道,并对该通道作一些初始化的工做  23  *  24  * @param port  25  * 绑定的端口号  26  * @throws IOException  27      */
 28     public void initServer(int port) throws IOException {  29         // 得到一个ServerSocket通道
 30         ServerSocketChannel serverChannel = ServerSocketChannel.open();  31         // 设置通道为非阻塞
 32         serverChannel.configureBlocking(false);  33         // 将该通道对应的ServerSocket绑定到port端口
 34         serverChannel.socket().bind(new InetSocketAddress(port));  35         // 得到一个通道管理器
 36         this.selector = Selector.open();  37         // 将通道管理器和该通道绑定,并为该通道注册SelectionKey.OP_ACCEPT事件,注册该事件后,  38         // 当该事件到达时,selector.select()会返回,若是该事件没到达selector.select()会一直阻塞。
 39  serverChannel.register(selector, SelectionKey.OP_ACCEPT);  40  }  41 
 42     /**
 43  * 采用轮询的方式监听selector上是否有须要处理的事件,若是有,则进行处理  44  *  45  * @throws IOException  46      */
 47     public void listen() throws IOException {  48         System.out.println("服务端启动成功!");  49         // 轮询访问selector
 50         while (true) {  51             // 当注册的事件到达时,方法返回;不然,该方法会一直阻塞
 52  selector.select();  53             // 得到selector中选中的项的迭代器,选中的项为注册的事件
 54             Iterator<?> ite = this.selector.selectedKeys().iterator();  55             while (ite.hasNext()) {  56                 SelectionKey key = (SelectionKey) ite.next();  57                 // 删除已选的key,以防重复处理
 58  ite.remove();  59 
 60  handler(key);  61  }  62  }  63  }  64 
 65     /**
 66  * 处理请求  67  *  68  * @param key  69  * @throws IOException  70      */
 71     public void handler(SelectionKey key) throws IOException {  72         
 73         // 客户端请求链接事件
 74         if (key.isAcceptable()) {  75  handlerAccept(key);  76             // 得到了可读的事件
 77         } else if (key.isReadable()) {  78  handelerRead(key);  79  }  80  }  81 
 82     /**
 83  * 处理链接请求  84  *  85  * @param key  86  * @throws IOException  87      */
 88     public void handlerAccept(SelectionKey key) throws IOException {  89         ServerSocketChannel server = (ServerSocketChannel) key.channel();  90         // 得到和客户端链接的通道
 91         SocketChannel channel = server.accept();  92         // 设置成非阻塞
 93         channel.configureBlocking(false);  94 
 95         // 在这里能够给客户端发送信息哦
 96         System.out.println("新的客户端链接");  97         // 在和客户端链接成功以后,为了能够接收到客户端的信息,须要给通道设置读的权限。
 98         channel.register(this.selector, SelectionKey.OP_READ);  99  } 100 
101     /**
102  * 处理读的事件 103  * 104  * @param key 105  * @throws IOException 106      */
107     public void handelerRead(SelectionKey key) throws IOException { 108         // 服务器可读取消息:获得事件发生的Socket通道
109         SocketChannel channel = (SocketChannel) key.channel(); 110         // 建立读取的缓冲区
111         ByteBuffer buffer = ByteBuffer.allocate(1024); 112         int read = channel.read(buffer); 113         if(read > 0){ 114             byte[] data = buffer.array(); 115             String msg = new String(data).trim(); 116             System.out.println("服务端收到信息:" + msg); 117             
118             //回写数据
119             ByteBuffer outBuffer = ByteBuffer.wrap("好的".getBytes()); 120             channel.write(outBuffer);// 将消息回送给客户端
121         }else{ 122             System.out.println("客户端关闭"); 123  key.cancel(); 124  } 125  } 126 
127     /**
128  * 启动服务端测试 129  * 130  * @throws IOException 131      */
132     public static void main(String[] args) throws IOException { 133         NIOServer server = new NIOServer(); 134         server.initServer(8000); 135  server.listen(); 136  } 137 
138 }
View Code
相关文章
相关标签/搜索