NIO相关概念之Selector
选择器(selector):
选择器管理者一个被注册的通道的集合信息和它们的就绪状态.通道是和选择器一起被注册的,并且使用选择器来更新通道的就绪状态,当这么做的时候,可以选择被激发的线程挂起,直到有就绪的通道
可选择通道(SelectableChannel)
这个抽象类提供了实现通道的可选择性所需要的公共方法。它是所有支持就绪检查的通道类的父类。FileChannel对象不是可选择的,因为它们没有继承SelectableChannel。所有socket通道都是可选择的,包括从管道(Pipe)对象的中获得的通道。SelectableChannel可以被注册到Selector对象上,同时可以指定对那个选择器而言,那种操作是感兴趣的。一个通道可以被注册到多个选择器上,但对每个选择器而言只能被注册一次。
选择键(SelectionKey)
选择键封装了特定的通道与特定的选择器的注册关系。选择键对象被SelectableChannel.register( ) 返回并提供一个表示这种注册关系的标记。选择键包含了两个比特集(以整数的形式进行编码),指示了该注册关系所关心的通道操作,以及通道已经准备好的操作。
就绪选择的相关类之间的关系如下:
调用可选择通道的register( )方法会将它注册到一个选择器上。如果您试图注册一个处于阻塞状态的通道,register( )将抛出未检查的IllegalBlockingModeException异常。
此外,通道一旦被注册,就不能回到阻塞状态。试图这么做的话,将在调用configureBlocking( )方法时将抛出IllegalBlockingModeException异常。并且,理所当然地,试图注册一个已经关闭的SelectableChannel实例的话,也将抛出ClosedChannelException异常,就像方法原型指示的那样
尽管SelectableChannel类上定义了register( )方法,还是应该将通道注册到选择器上,而不是另一种方式。选择器维护了一个需要监控的通道的集合。一个给定的通道可以被注册到多于一个的选择器上,而且不需要知道它被注册了那个Selector对象上。将register( )放在SelectableChannel上而不是Selector上,这种做法看起来有点随意。它将返回一个封装了两个对象的关系的选择键对象。重要的是要记住选择器对象控制了被注册到它之上的通道的选择过程。
选择器才是提供管理功能的对象,而不是可选择通道对象。选择器对象对注册到它之上的通道执行就绪选择,并管理选择键。
对于键的interest(感兴趣的操作)集合和ready(已经准备好的操作)集合的解释是和特定的通道相关的。每个通道的实现,将定义它自己的选择键类。在register( )方法中构造它并将它传递给所提供的选择器对象。
以下是一个基于selector来实现的一个Http服务器端:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.nio.charset.Charset;
import java.util.Iterator;
/**
* Created with Intellij IDEA
*
* @author: jiaoyiping
* Mail: jiaoyiping@gmail.com
* Date: 2018/07/22
* Time: 11:18
* To change this template use File | Settings | Editor | File and Code Templates
*/
public class HttpServer {
private static final Logger logger = LoggerFactory.getLogger(HttpServer.class);
private static final int DEFAULT_TIME_OUT = 3000;
private static final int DEFAULT_HTTP_PORT = 8080;
public static void main(String[] args) throws IOException {
Selector selector = Selector.open();
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.configureBlocking(false);
serverSocketChannel.bind(new InetSocketAddress(DEFAULT_HTTP_PORT));
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
while (true) {
if (selector.select(DEFAULT_TIME_OUT) == 0) {
logger.info("没有接收到客户端的请求,继续等待");
continue;
}
Iterator<SelectionKey> keyIterator = selector.selectedKeys().iterator();
Handler handler = new Handler();
while (keyIterator.hasNext()) {
SelectionKey key = keyIterator.next();
if (key.isAcceptable()) {
handler.handleAccept(key);
}
if (key.isReadable()) {
handler.handleRead(key);
}
keyIterator.remove();
}
}
}
private static class Handler {
private static final int DEFAULT_BUFFER_SIZE = 4096;
private static final String DEFAULT_HTTP_RESPONSE_HEADER = "HTTP/1.1 200 OK\nContent-Type: text/html;charset=UTF-8\n\r\n";
private static final String DEFAULT_CHAR_SET = "UTF-8";
public void handleAccept(SelectionKey key) throws IOException {
SocketChannel socketChannel = ((ServerSocketChannel) key.channel()).accept();
socketChannel.configureBlocking(false);
socketChannel.register(key.selector(), SelectionKey.OP_READ, ByteBuffer.allocate(DEFAULT_BUFFER_SIZE));
}
public void handleRead(SelectionKey key) throws IOException {
SocketChannel socketChannel = (SocketChannel) key.channel();
ByteBuffer buffer = (ByteBuffer) key.attachment();
buffer.clear();
if (socketChannel.read(buffer) == -1) {
logger.debug("没有从请求中读取到内容");
socketChannel.close();
return;
}
buffer.flip();
String receivedString = Charset.forName(DEFAULT_CHAR_SET).newDecoder().decode(buffer).toString();
logger.info("收到了客户端的请求:\n{}", receivedString);
//返回数据给客户端
String message = "<html><body>黄河远上白云间</body></html>";
ByteBuffer sendData = ByteBuffer.wrap((DEFAULT_HTTP_RESPONSE_HEADER + message).getBytes());
socketChannel.write(sendData);
socketChannel.close();
}
}
}
NIO相关概念之Selector的更多相关文章
- epoll浅析以及nio中的Selector
出处: https://my.oschina.net/hosee/blog/730598 首先介绍下epoll的基本原理,网上有很多版本,这里选择一个个人觉得相对清晰的讲解(详情见reference) ...
- epoll 浅析以及 nio 中的 Selector
首先介绍下epoll的基本原理,网上有很多版本,这里选择一个个人觉得相对清晰的讲解(详情见reference): 首先我们来定义流的概念,一个流可以是文件,socket,pipe等等可以进行I/O操作 ...
- 两种 NIO 实现:Selector 与 Epoll
[总结]两种 NIO 实现:Selector 与 Epoll 时间2012-11-17 08:38:42 开源中国新闻原文 http://my.oschina.net/ielts0909/blog/ ...
- Java I/O(4):AIO和NIO中的Selector
您好,我是湘王,这是我的博客园,欢迎您来,欢迎您再来- 在Java NIO的三大核心中,除了Channel和Buffer,剩下的就是Selector了.有的地方叫它选择器,也有叫多路复用器的(比如Ne ...
- 【总结】两种 NIO 实现:Selector 与 Epoll
时间2012-11-17 08:38:42 开源中国新闻原文 http://my.oschina.net/ielts0909/blog/89849 我想用这个话题小结下最近这一阶段的各种测试和开发. ...
- 7. 彤哥说netty系列之Java NIO核心组件之Selector
--日拱一卒,不期而至! 你好,我是彤哥,本篇是netty系列的第七篇. 简介 上一章我们一起学习了Java NIO的核心组件Buffer,它通常跟Channel一起使用,但是它们在网络IO中又该如何 ...
- 3、nio中的selector使用
通过编写一个客户端和服务器端的例子来熟悉selector的使用 服务端逻辑: 1. 绑定一个端口号2. channel注册到selector中3. 用死循环来监听如果有时间发生,遍历selection ...
- NIO(三):Selector选择器
一.堵塞式与非堵塞式 在传统IO中,将数据由当前线程从客户端传入服务端,由服务端的内核进行判断传过来的数据是否合法,内核中是否存在数据. 如果不存在数据 ,并且数据并不合法,当前线程将会堵塞等待.当前 ...
- Java NIO之选择器Selector
在单独的线程中,检查多个通道是否可以进行IO操作. Selector创建:静态工厂方法创建 Selector selector = Selector.open(); 注册通道 channel.conf ...
随机推荐
- RxJava2 源码解析(一)
概述 最近事情太多了,现在公司内部的变动,自己岗位的变化,以及最近决定找工作.所以博客耽误了,准备面试中,打算看一看RxJava2的源码,遂有了这篇文章. 不会对RxJava2的源码逐字逐句的阅读,只 ...
- android ndk-build 编译静态库libxx.a 以及Android studio openssl 静态库配置(cmake)
android ndk-build 编译静态库libxx.a 需求场景: 目前有安卓编码好的现在的openssl的两个.a,我们需要调用openssl的函数,并把功能再封装成.a; 这样使用时,在an ...
- .Net学习资料
1.博客系列文章 (1)设计模式 吕震宇 设计模式 张逸:晴窗笔记 Design & Pattern 梦幻Dot Net .Net设计模式 李会军 .NET设计模式系列文章 ...
- Java Arrays.sort源代码解析
前提: 当用到scala的sortWith,发现: def sortWith(lt: (A, A) ⇒ Boolean): List[A] // A为列表元素类型 根据指定比较函数lt进行排序,且排序 ...
- gdb 拾遗
1,跳过某个特定信号 (gdb) handle SIGPIPE nostop noprint pass 2,break在特定的系统调用处 (gdb) catch syscall 3 3,遇到一个断点的 ...
- 在Windows服务器上启用TLS 1.2及TLS 1.2基本原理
在Windows服务器上启用TLS 1.2及TLS 1.2基本原理 在Windows服务器上启用TLS 1.2及TLS 1.2基本原理 最近由于Chrome40不再支持SSL 3.0了,GOOGLE认 ...
- Python 隔离沙箱 virtualenv
我认为Python一个很大的优势就是官方网站给出的众多的软件包,几乎能帮助你实现你想要的任何功能,避免了重复开发的劳动,但是零零碎碎的包,以及每个包的各种各样的版本管理就成为了一个比较棘手的问题,因此 ...
- 湾区求职分享:三个月刷题拿到 Google offer,欢迎踊跃提问
本文仅以个人经历和个人观点作为参考.如能受益,不胜荣幸. 本文会不断的修正,更新.希望通过大家的互动最后能写出一份阅者受益的文章. 本文纯手打,会有错别字,欢迎指出,虚心接受及时更改. 小马过河,大牛 ...
- intellij IDEA 安装和配置和使用
下载:https://www.jetbrains.com/idea/download/download-thanks.html?platform=windows 安装教程:https://blog.c ...
- [转]Java NIO 系列教程
Java NIO提供了与标准IO不同的IO工作方式: Channels and Buffers(通道和缓冲区):标准的IO基于字节流和字符流进行操作的,而NIO是基于通道(Channel)和缓冲区(B ...