NIO组件Selector调用实例
来源:互联网 发布:矩阵扰动 编辑:程序博客网 时间:2024/04/30 13:36
*对于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,EchoSelectorProtocolprivate 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); //nonblockinglistnChannel.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 otherscontinue;}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;}@Overridepublic 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));}@Overridepublic 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);}@Overridepublic 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详解
- java-nio之Selector组件
- Java NIO编程实例之三Selector
- NIO---selector
- NIO Selector
- NIO-Selector
- NIO Selector
- NIO Selector
- NIO组件Selector工作机制详解(上)
- NIO组件Selector工作机制详解(下)
- Java NIO Selector详解(含多人聊天室实例)
- 调用aspjpeg组件实例
- Java NIO学习(三)Selector监听事件+NIO服务器实例
- Java NIO Selector
- NIO:Selector 类用法
- NIO:Selector 详解
- JAVA NIO之selector
- NHibernate记录
- ios block初级使用
- DSP6000的上电及供电
- jquery flot 在节点上显示提示
- UVA 1423 - Guess(拓扑排序)
- NIO组件Selector调用实例
- Mat, vector<point2f>,Iplimage等等常见类型转换
- 上位机与PLC通讯及OPC数据采集实践一
- 在openshift上构建自己的应用
- How to Find the Offending SQL from a ORA-600 or ORA-7445 Trace File (文档 ID 154170.1)转到底部 In this
- 由集成电流传感器MAX471构成±3A电流监测仪的电路
- 读书札记-2013年12月
- DSP6000的几个简单优化技巧
- String类型是不可变的