源码时代JAVA干货分享|利用NIO模拟实现Tomcat容器!
NIO是什么
New IO,始于Java1.4,提供新的非阻塞 JavaIO 操作API.
又称Non-Blocking IO 非阻塞IO
替代旧版本的Blocking IO, 多用于网络相关的API.
成都创新互联公司,为您提供重庆网站建设公司、成都网站制作公司、网站营销推广、网站开发设计,对服务房屋鉴定等多个行业拥有丰富的网站建设及推广经验。成都创新互联公司网站建设公司成立于2013年,提供专业网站制作报价服务,我们深知市场的竞争激烈,认真对待每位客户,为客户提供赏心悦目的作品。 与客户共同发展进步,是我们永远的责任!
为什么要使用NIO
使用NIO后,WEB网络程序性能可以进一步提高
模拟Tomcat7, 阻塞IO处理Http请求:
public class BIOHttpServer {
public static void main(String[] args) throws IOException {
ServerSocket socket = new ServerSocket(8080);
System.out.println(Thread.currentThread().getName()+"启动:"+8080);
while(true){
Socket accept = socket.accept();
InputStream inputStream = accept.getInputStream();
byte[] b = new byte[1024];
inputStream.read(b);
System.out.println(new String(b));
// http响应头 必须这样写:
String response = "HTTP/1.1 200 ok\r\nContent-Length: 11\r\n\r\nHello World\r\n";
accept.getOutputStream().write(response.getBytes());
accept.getOutputStream().flush();
accept.close();
}
}
}
NIO高性能的核心原理:
发起连接
操作系统接收连接
TCP模块 + 多路复用机制
一个Java线程通过Selector工具选择性处理
有数据传输的交给线程池
最终达到,线程最大程度利用
使用NIO:
模拟Tomcat8.5, NIO处理Http请求:
public class NIOHttpServer {
public static void main(String[] args) throws IOException {
// 1.ServerSocketChannel 绑定端口
ServerSocketChannel socket = ServerSocketChannel.open();
socket.configureBlocking(false); // no-Blocking
socket.bind(new InetSocketAddress(8080));
System.out.println("NIO服务器启动,端口:"+8080);
// 2.获取新连接
// selector 获取不同操作系统下不同的tcp连接动态
Selector selector = Selector.open();
// 选择器,根据条件查询符合情况地TCP连接
socket.register(selector, SelectionKey.OP_ACCEPT);
while(true){
selector.select(1000); //如果没有新连接,就等待
// 3. 处理查询结果
Set keys = selector.selectedKeys();
Iterator iterator = keys.iterator();
while(iterator.hasNext()){
SelectionKey result = iterator.next();
//根据不同的类型,分别进行处理
if(result.isAcceptable()){ //3.1 拿到新连接对象
// nio体现,accept 不阻塞,没有连接则返回null
SocketChannel accept = socket.accept();
if(accept!=null){
// 注册连接对象,进行关注
accept.configureBlocking(false);// no-Blocking
accept.register(selector, SelectionKey.OP_READ);
}
}
if(result.isReadable()){ //3.2 有数据请求的连接
SocketChannel channel = (SocketChannel) result.channel();
// 处理过程中,先取消selector对应连接的注册,避免重复
result.cancel();
// NIO的读写方式: 字节缓冲区
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
channel.read(byteBuffer);
byteBuffer.flip(); //模式转换
byte[] b = byteBuffer.array();
String request = new String(b);
//处理请求...
System.out.println(request);
//数据响应:NIO的写数据
String response = "HTTP/1.1 200 ok\r\nContent-Length: 11\r\n\r\nHello World\r\n";
channel.write(ByteBuffer.wrap(response.getBytes()));
// 处理完成,重新注册,继续接收处理新的连接
// channel.register(selector, SelectionKey.OP_READ);
}
// 删除处理过的结果(事件)
iterator.remove();
}
// 检查过程就绪,清除之前的调用效果
selector.selectNow();
}
}
}
(本文章由源码时代技术老师原创,转载请注明出处!)
分享标题:源码时代JAVA干货分享|利用NIO模拟实现Tomcat容器!
分享网址:http://ybzwz.com/article/gigpcc.html