NIO组件Selector调用实例
*对于nio的非阻塞I/O操作,使用Selector获取哪些I/O准备就绪,注册的SelectionKey集合记录关联的Channel这些信息.SelectionKey记录Channel对buffer的操作方式.
---SelectableChannel,Selector,SelectionKey是nio中Channel操作的3个主要部件.
---对应关系,
一个SelectableChannel,记录了一组注册的SelectionKey[]
一个SelectionKey,关联了一个Channel和一个Selector.
一个Selector,维护着注册的一组SelectionKey
*使用示例
---注,这段代码来自"TCP/IP Sockets in Java",典型示例,我做了注解
package chapter5; import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.util.Iterator; public class TCPServerSelector {
private static final int BUFSIZE = 256; //Buffer,EchoSelectorProtocol
private static final int TIMEOUT = 3000; //Selector.select(long timeout) public static void main(String[] args) throws IOException {
if(args.length<1){
throw new IllegalArgumentException("Parameter(s): <Port> ...");
} Selector selector =Selector.open(); //创建Selector实例
for(String arg:args){
ServerSocketChannel listnChannel =ServerSocketChannel.open();
listnChannel.socket().bind(new InetSocketAddress(Integer.parseInt(arg)));
listnChannel.configureBlocking(false); //nonblocking
listnChannel.register(selector, SelectionKey.OP_ACCEPT); //Channel注册selector,并告知channel感兴趣的操作
} TCPProtocol protocol =new EchoSelectorProtocol(BUFSIZE);
while(true){ //循环
if(selector.select(TIMEOUT)==0){ //返回准备就绪I/O的SelectionKey数
System.out.println("."); //to do others
continue;
} Iterator<SelectionKey> keyIter =selector.selectedKeys().iterator();//获取已选的SelectionKey集合
while(keyIter.hasNext()){ //遍历key,根据key的类型做相应处理
SelectionKey key =keyIter.next();
if(key.isAcceptable())
protocol.handleAccept(key); if(key.isReadable())
protocol.handleRead(key); //SelectionKey is invalid if it is cancelled, its channel is closed, or its selector is closed.
if(key.isValid() && key.isWritable())
protocol.handleWrite(key); keyIter.remove(); //手动清空,因为Selector只会在已选的SelectionKey集中添加
}
} }
}
package chapter5; import java.io.IOException;
import java.nio.channels.SelectionKey; public interface TCPProtocol {
void handleAccept(SelectionKey key) throws IOException;
void handleRead(SelectionKey key) throws IOException;
void handleWrite(SelectionKey key) throws IOException;
} package chapter5; import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel; public class EchoSelectorProtocol implements TCPProtocol { private int bufSize; public EchoSelectorProtocol(int bufSize){
this.bufSize =bufSize;
} @Override
public void handleAccept(SelectionKey key) throws IOException {
SocketChannel clntChan = ((ServerSocketChannel)key.channel()).accept();
clntChan.configureBlocking(false);
//对于已注册Selector的Channel,再次调用就更新注册信息,这里更新了SelectionKey的类型和附件,附件是需要操作的buffer.
clntChan.register(key.selector(), SelectionKey.OP_READ,ByteBuffer.allocate(bufSize));
} @Override
public void handleRead(SelectionKey key) throws IOException {
SocketChannel clntChan =(SocketChannel)key.channel();
ByteBuffer buf =(ByteBuffer) key.attachment(); //获取附件
long bytesRead = clntChan.read(buf);
if(bytesRead==-1) //channel已读到结束位置
clntChan.close();
else if(bytesRead > 0)
key.interestOps(SelectionKey.OP_READ|SelectionKey.OP_WRITE);
} @Override
public void handleWrite(SelectionKey key) throws IOException {
ByteBuffer buf =(ByteBuffer) key.attachment();
buf.flip();
SocketChannel clntChan =(SocketChannel) key.channel();
clntChan.write(buf);
if(!buf.hasRemaining()){
key.interestOps(SelectionKey.OP_READ); //设置Key的兴趣集
}
buf.compact();
} }
看了代码,如何使用就清楚了吧:).
下面再做些细节说明
*Selector
---更新准备好的SelectionKey,移除isValid()为false的SelectionKey
select() //阻塞等待,直至一个channel准备好或调用wakeup()才返回
select(long timeout) //如上,返回条件多了个超时时间
selectNow() //非阻塞,会立刻返回,没有时返回值=0
wakeup() //使得Selector返回
注意,select()会在上次已选择的键集中添加这次的可用键,故在2次select之间,手动移除已处理的SelectionKey.
*SelectionKey
---兴趣操作集,通过它就可以知道channel可以去做哪些事了.有4种类型,如下:
public static final int OP_READ = 1 << 0;
public static final int OP_ACCEPT = 1 << 4;
public static final int OP_WRITE = 1 << 2;
public static final int OP_CONNECT = 1 << 3;
通过SelectionKey.interestOps(int ops)就可以配置这些值
---附件,主要作用是为channel处理提供辅助信息,如上面示例中att为ByteBuffer
SelectionKey.attach(Object ob) //添加附件,另一种方式SelectableChannel.register(Selector sel, int ops, Object att)
SelectionKey.attachment() //获取附件
---SelectionKey.cancel(),永久的注销键,加入Selector的注销集中,在下次select()时被移除
NIO组件Selector调用实例的更多相关文章
- NIO组件Selector工作机制详解(上)
转自:http://blog.csdn.net/haoel/article/details/2224055 一. 前言 自从J2SE 1.4版本以来,JDK发布了全新的I/O类库,简称NIO,其不但 ...
- NIO组件 Selector(选择器)
简介 使用Selector(选择器), 可以使用一个线程处理多个客户端连接. Selector 能够检测多个注册的通道上是否有事件发生(多个Channel以事件的方式可以注册到同一个Selector) ...
- NIO组件Selector详解
Selector(选择器)是Java NIO中能够检测一到多个NIO通道,并能够知晓通道是否为诸如读写事件做好准备的组件.这样,一个单独的线程可以管理多个channel,从而管理多个网络连接. 下面是 ...
- NIO组件Selector工作机制详解(下)
转自:http://blog.csdn.net/haoel/article/details/2224069 五. 迷惑不解 : 为什么要自己消耗资源? 令人不解的是为什么我们的Java的New I/ ...
- NIO的Selector
参考自 Java NIO系列教程(六) Selector Java-NIO-Selector java.nio.channels.Selector NIO新功能Top 10(下) 出发点: 如何管理多 ...
- NIO 概述 与 通信实例
NIO 简述: NIO是在jdk1.4之后加入的一种基于缓冲区(buffer)和通道(channel)的I/O方式, nio是同步非阻塞的i/o模式,同步是指线程不断地轮询i/o事件,非阻塞是在处理i ...
- Java NIO之Selector(选择器)
历史回顾: Java NIO 概览 Java NIO 之 Buffer(缓冲区) Java NIO 之 Channel(通道) 其他高赞文章: 面试中关于Redis的问题看这篇就够了 一文轻松搞懂re ...
- Nio使用Selector客户端与服务器的通信
使用NIO的一个最大优势就是客户端于服务器自己的不再是阻塞式的,也就意味着服务器无需通过为每个客户端的链接而开启一个线程.而是通过一个叫Selector的轮循器来不断的检测那个Channel有消息处理 ...
- WPF中实例化Com组件,调用组件的方法时报System.Windows.Forms.AxHost+InvalidActiveXStateException的异常
WPF中实例化Com组件,调用组件的方法时报System.Windows.Forms.AxHost+InvalidActiveXStateException的异常 在wpf中封装Com组件时,调用组件 ...
随机推荐
- [python][flask][flask-SQLAlchemy]关于flask-SQLAlchemy的初级使用教程
鉴于网上关于flask-SQLAlchemy的实例使用教程参差不齐,于此写下工作学习过程中的使用过程,以便分享交流. 对于python关于flask有一定了解的高端玩家来说,请转至flask官方开发文 ...
- Python学习笔记——正则表达式入门
# 本文对正则知识不做详细解释,仅作入门级的正则知识目录. 正则表达式的强大早有耳闻,大一时参加一次选拔考试,题目就是用做个HTML解析器,正则的优势表现得淋漓尽致.题外话不多讲,直接上干货: 1. ...
- LeetCode【第217题】Contains Duplicate
题目: ''' Given an array of integers, find if the array contains any duplicates. Your function should ...
- linux的getcwd和readlink的区别
针对linux下的程序,有两个路径: 1>运行程序的路径; 2>可执行文件所在的路径 例如: 如果我在/home/yongchao下执行 $ ./temp/test 那么 运行程序的 ...
- 将UIImage保存到iOS照片库和对应程序沙盒中-b
1.保存到iOS照片库需要引入QuartzCore.framework框架,具体代码如下:.h文件#import <QuartzCore/QuartzCore.h>UIImageView ...
- [原博客] POI系列(1)
正规.严谨.精妙. -POI 发现POI(波兰信息学奥赛)的题都很有意思.于是开刷bzoj上的poi题目(按ac人数降序..).顺手写一写题解,加深印象. 为了防止一篇文章过于长,打算每五道题另起一篇 ...
- 【Ecmall】ECMall2.x模板制作入门系列(认识ECMall模板)
ECMall2.x模板制作入门系列之1(认识ECMall模板) 从ECMall2.0全新架构发布以来,随着版本的不断更新,ECMall已经逐渐走向一个稳定时期,是时候整理一些实用教程了.下面给大家带来 ...
- 使用 .NET 平台,如何玩转 Universal Windows 应用?
2015年7月30日 本文作者是 Managed Languages 团队项目经理 Lucian Wischik. 不久前,Visual Studio 2015上新增 Windows 10 应用的开发 ...
- 【BZOJ 3926】 [Zjoi2015]诸神眷顾的幻想乡 (广义SAM)
3926: [Zjoi2015]诸神眷顾的幻想乡 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 974 Solved: 573 Descriptio ...
- 【Xamarin挖墙脚系列:Xamarin.Android的API设计准则】
原文:[Xamarin挖墙脚系列:Xamarin.Android的API设计准则] 前言 楼主也是看着Xamarin的官方文档来的.基本也是照猫画虎.英语勉强凑合.翻译的不对的地方,大家多多指教.(这 ...