前文介绍了传统IO的WEB经典服务器 reactor模式前序:传统IO的WEB服务器设计
下面看看JAVA NIO的WEB服务器设计
NIO是基于事件驱动的,对于NIO来说,重要组件是Selector,其服务器代码为:
/*
* 流程总结:
* 1.初始时,只对accept事件感兴趣,selectionkey只有accept事件
* 2.当有连接进来时,处理完accept之后,对读事件感兴趣,selectionkey增加键read
* 3.不断循环selectionkey的键集合
*/
Selector selector = Selector.open();
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.configureBlocking(false); // 设置为非阻塞
// 绑定监听端口号
serverSocketChannel.bind(new InetSocketAddress(8899));
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); // 对连接事件感兴趣
while (true) {
Set<SelectionKey> keys = selector.selectedKeys();
Iterator<SelectionKey> iterator = keys.iterator();
while(iterator.hasNext()) {
SelectionKey selectionKey = iterator.next();
if(selectionKey.isAcceptable()) {
ServerSocketChannel serverSocketChannel1 = (ServerSocketChannel) selectionKey.channel();
SocketChannel socketChannel = serverSocketChannel1.accept(); // 此处阻塞
socketChannel.configureBlocking(false);
socketChannel.register(selector, SelectionKey.OP_READ);
iterator.remove();
} else if(selectionKey.isReadable()) { // 完成功能:从客户端接收数据并且原样返回给客户端
SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
while (true) {
ByteBuffer byteBuffer = ByteBuffer.allocate(512);
byteBuffer.clear();
int read = socketChannel.read(byteBuffer);
if(read <= 0) {
break; // 数据已接收完毕
}
byteBuffer.flip();
socketChannel.write(byteBuffer);
}
iterator.remove();
}
}
}