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
相關文章
相關標籤/搜索