NIO-结合Selector设计一个简易WebServer
来源:互联网 发布:淘宝保暖卫衣长款 编辑:程序博客网 时间:2024/06/07 01:44
参考资料
建议大家找找这种资料来了解下什么是IO,什么是NIO,NIO的理念是什么。
一点小结论
Channel、Buffer、Selector是NIO的核心API。
Channel类似旧IO的流,可读可写,读写都是面向Buffer。
Channel通常来自文件或网络:
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();……RandomAccessFile randomAccessFile = new RandomAccessFile("/Users/zhengwei/lanqiao/ConditionOperator.java", "rw");FileChannel channel = randomAccessFile.getChannel();
Selector是非阻塞的核心,不像以前所有的读写都要阻塞,如果要并发就必须开多线程来监听每一路的IO。Selector有一种注册机制,首先读写事件不阻塞,只需向Selector注册感兴趣的事件,这样CPU可以去干点别的事,只需定期轮询Selector即可。
简易Server的实现思路
打开Server通道,并做初始化initServerChannel
实例化一个Selector,对Server通道的连接就绪事件感兴趣:
//打开一个选择器 Selector selector = Selector.open();// Selector的创建 serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);// 对channel的连接就绪感兴趣
轮询Selector状态,如果出现连接事件,实例化一个客户端套接字连接通道,将这个通道上的可读事件注册给Selector;
if (key.isAcceptable()) { dealAcceptable(serverSocketChannel, selector);}
如果出现可读事件,读取客户端的HTTP连接报文,写回一段HTTP响应报文;
else if (key.isReadable()) {// 有读的事儿没? dealReadable(selector, key); }
如果出现可写事件,完成内容写,并关闭连接。
else if (key.isWritable()) { dealWritable(key);}
完整代码
package org.lanqiao.nio;import java.io.IOException;import java.net.InetSocketAddress;import java.net.ServerSocket;import java.nio.ByteBuffer;import java.nio.channels.SelectionKey;import java.nio.channels.Selector;import java.nio.channels.ServerSocketChannel;import java.nio.channels.SocketChannel;import java.util.HashSet;import java.util.Iterator;import java.util.Set;public class Server implements Runnable { //Server启停标志 private boolean interrupted = false; public void run() { try { ServerSocketChannel serverSocketChannel = initServerChannel(); //打开一个选择器 Selector selector = Selector.open();// Selector的创建 serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);// 对channel的连接就绪感兴趣 while (!interrupted) { //查询就绪的通道数量,这是一个阻塞方法 int readyChannels = selector.select(500); //没有就绪的则继续进行循环 if (readyChannels == 0) continue; final Set<SelectionKey> selectionKeys = selector.selectedKeys();// 啥事,阻塞 //迭代当前已发生的事件 Iterator<SelectionKey> keyIterator = selectionKeys.iterator(); while (keyIterator.hasNext()) { SelectionKey key = keyIterator.next(); if (key.isAcceptable()) { dealAcceptable(serverSocketChannel, selector); } else if (key.isConnectable()) { // a connection was established with a remote server. } else if (key.isReadable()) {// 有读的事儿没? dealReadable(selector, key); } else if (key.isWritable()) { dealWritable(key); } //从key集合中删除key,这一步很重要 keyIterator.remove(); } } } catch (IOException e) { e.printStackTrace(); } } private void dealWritable(SelectionKey key) throws IOException { // a channel is ready for writing SocketChannel clientChannel = (SocketChannel) key.channel(); clientChannel.shutdownInput(); clientChannel.close(); } private void dealReadable(Selector selector, SelectionKey key) { // a channel is ready for reading //该key有Read事件 SocketChannel clientChannel = (SocketChannel) key.channel(); String lines = NIOx.readAllLine(clientChannel); System.out.println("lines===\n" + lines); try { clientChannel.register(selector, SelectionKey.OP_WRITE); //书写报文 clientChannel.write(ByteBuffer.wrap(( "HTTP/1.1 200 OK\n" + "Date: Sat, 4 Nov 2017 23:59:59 GMT\n" + "Content-Type: text/html;charset=utf-8\n" + "Content-Length: 5\n" + "\n" + "hello").getBytes())); } catch (IOException e) { e.printStackTrace(); } } private void dealAcceptable(ServerSocketChannel serverSocketChannel, Selector selector) throws IOException { //该key有ACCEPT事件 //将监听得到的channel强转为ServerSocketChannel // a connection was accepted by a ServerSocketChannel. //得到接收到的SocketChannel SocketChannel clientChannel = serverSocketChannel.accept(); clientChannel.configureBlocking(false);// 打死不阻塞 clientChannel.register(selector, SelectionKey.OP_READ); } private ServerSocketChannel initServerChannel() throws IOException { //打开ServerSocketChannel通道 ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); //得到ServerSocket对象 final ServerSocket serverSocket = serverSocketChannel.socket(); //监听端口 serverSocket.bind(new InetSocketAddress(8082)); //配置为非阻塞 serverSocketChannel.configureBlocking(false); return serverSocketChannel; } public static void main(String[] args) { new Thread(new Server()).start(); }}
阅读全文
0 0
- NIO-结合Selector设计一个简易WebServer
- 一个简易的WebServer程序
- 一个简易的WebServer实现
- Nio--Selector实现简易的http服务器
- Nio--Selector实现简易的http服务器
- 用C开发一个简易的webserver
- NIO---selector
- NIO Selector
- NIO-Selector
- NIO Selector
- NIO Selector
- 设计一个简易计算器
- 使用java nio的selector做一个数据查询主机
- androidUI设计:shape和selector的结合使用
- linux配置webserver简易步骤
- 使用NanoHttpd实现简易WebServer
- ASP.NET一个简易的WebServer,用控制台程序模拟IIS服务器 托起web服务
- ASP.NET一个简易的WebServer,用控制台程序模拟IIS 托起web服务
- 11.4 总结
- 第八周——“对称矩阵压缩存储的实现与应用”
- OSI 七层 及相关协议
- 装饰器、迭代器、生成器
- spring:控制反转
- NIO-结合Selector设计一个简易WebServer
- 滑动条
- ButterKnife之@OnTouch——界面交互效果进阶
- 5.4
- 变量的声明
- git stash 命令用法
- PAT 1005. 继续(3n+1)猜想 (25)
- InfoGAN 论文阅读笔记 基本知识总结
- [leetcode]169. Majority Element