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 }