前文介绍了传统IO的WEB经典服务器 reactor模式前序:传统IO的WEB服务器设计
下面看看JAVA NIO的WEB服务器设计
NIO是基于事件驱动的,对于NIO来说,重要组件是Selector,其服务器代码为:
1 /* 2 * 流程总结: 3 * 1.初始时,只对accept事件感兴趣,selectionkey只有accept事件 4 * 2.当有连接进来时,处理完accept之后,对读事件感兴趣,selectionkey增加键read 5 * 3.不断循环selectionkey的键集合 6 */ 7 8 Selector selector = Selector.open(); 9 ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); 10 serverSocketChannel.configureBlocking(false); // 设置为非阻塞 11 12 // 绑定监听端口号 13 serverSocketChannel.bind(new InetSocketAddress(8899)); 14 15 serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); // 对连接事件感兴趣 16 17 while (true) { 18 Set<SelectionKey> keys = selector.selectedKeys(); 19 20 Iterator<SelectionKey> iterator = keys.iterator(); 21 22 while(iterator.hasNext()) { 23 SelectionKey selectionKey = iterator.next(); 24 25 if(selectionKey.isAcceptable()) { 26 ServerSocketChannel serverSocketChannel1 = (ServerSocketChannel) selectionKey.channel(); 27 SocketChannel socketChannel = serverSocketChannel1.accept(); // 此处阻塞 28 socketChannel.configureBlocking(false); 29 30 socketChannel.register(selector, SelectionKey.OP_READ); 31 32 iterator.remove(); 33 } else if(selectionKey.isReadable()) { // 完成功能:从客户端接收数据并且原样返回给客户端 34 SocketChannel socketChannel = (SocketChannel) selectionKey.channel(); 35 36 while (true) { 37 ByteBuffer byteBuffer = ByteBuffer.allocate(512); 38 byteBuffer.clear(); 39 int read = socketChannel.read(byteBuffer); 40 41 if(read <= 0) { 42 break; // 数据已接收完毕 43 } 44 45 byteBuffer.flip(); 46 socketChannel.write(byteBuffer); 47 48 } 49 50 iterator.remove(); 51 52 } 53 54 55 } 56 57 }