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 }