java中NIO的selector

Posted 健康平安的活着

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java中NIO的selector相关的知识,希望对你有一定的参考价值。

一 selector

Selector(选择器)是Java NIO中能够检测一到多个NIO通道,并能够知晓通道是否为诸如读写事件做好准备的组件,一个Selector可以同时轮询多个Channel,只需要一个线程负责Selector的轮询,就可以接入成千上万的客户端。

 二 selector的操作

1.selector的创建

Selector的创建
通过调用Selector.open()方法创建一个Selector,如下:
Selector selector = Selector.open();
2.向selector注册管道
为了将Channel和Selector配合使用,必须将channel注册到selector上。通过SelectableChannel.register()方法来实现,如下:
channel.configureBlocking(false);
SelectionKey key = channel.register(selector, Selectionkey.OP_READ);
3. SelectionKey
当向Selector注册Channel时,register()方法会返回一个SelectionKey对象。
4.interest集合
就像向Selector注册通道一节中所描述的,interest集合是你所选择的感兴趣的事件集合。
5. ready集合
ready 集合是通道已经准备就绪的操作的集合。
6.selectedKeys()
当像Selector注册Channel时,Channel.register()方法会返回一个SelectionKey 对象

 三 selector的案例操作

3.1 客户端

package com.cf.demo.nio.selector;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;

public class SelectorClient {
	private Selector selector;
	private SocketChannel channel = null;
	private ByteBuffer outBuff =  ByteBuffer.allocate(1024);
	private ByteBuffer inBuff =  ByteBuffer.allocate(1024);
	private int keys = 0;

	
	public static void main(String[] args) throws IOException {
		new SelectorClient().start();
	}
	
	public void start() throws IOException {
		initClient();
		listen();
	}
	
	public void initClient() throws IOException {
		channel = SocketChannel.open();
		selector = Selector.open();
		
		channel.configureBlocking(false);
		
		channel.connect(new InetSocketAddress("127.0.0.1", 8888));
		channel.register(selector, SelectionKey.OP_CONNECT);
	}
	
	public void listen () throws IOException {
		while(true) {
			//
			keys = this.selector.select();
			if (keys > 0)  {
				Iterator it = this.selector.selectedKeys().iterator();		
				while (it.hasNext()) {
					SelectionKey key = (SelectionKey) it.next();
					it.remove();
					
					if (key.isConnectable()) {
					
						SocketChannel channel = (SocketChannel) key.channel();
						if (channel.isConnectionPending()) {
							channel.finishConnect();
							System.out.println("Complete connect.");
						}
						
						channel.register(selector, SelectionKey.OP_WRITE);
					} else if (key.isWritable()) {
						SocketChannel channel = (SocketChannel) key.channel();
						outBuff.clear();
						System.out.println("client is write data start.");

						channel.write(outBuff.wrap("I'm client.".getBytes()));
						channel.register(selector, SelectionKey.OP_READ);
						System.out.println("client is write data end.");

					} else if (key.isReadable()) {
						// read
						SocketChannel channel = (SocketChannel) key.channel();
						inBuff.clear();
						
						int length = channel.read(inBuff);
						String msg = "server receive msg:" + new String(inBuff.array(), 0, length);
						System.out.println(msg);
					}
				}
				
			}
		}
	}

}

3.2 服务端:

package com.cf.demo.nio.selector;

import java.io.IOException;
import java.net.InetSocketAddress;
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.Iterator;

public class SelectorServer {
	private Selector selector;
	private ServerSocketChannel serverChannel = null;
	private int keys = 0;
	
	public static void main(String[] args) throws IOException {
		// TODO Auto-generated method stub
		new SelectorServer().start();
	}
	
	public void start() throws IOException {
		initServer();
		listen();
	}
	
	public void initServer() throws IOException {
		// 获取一个sokcet通道,
		serverChannel = ServerSocketChannel.open();
		// 获取一个通道管理器
		selector = Selector.open();
		// 非阻塞
		serverChannel.configureBlocking(false);
		// 连接服务器
		serverChannel.socket().bind(new InetSocketAddress("127.0.0.1", 8888));
		// 吧serverChannel这个通道注册到管理器对象selector中去,当有客户端连接时触发
		serverChannel.register(selector, SelectionKey.OP_ACCEPT);		
	}
	
	public void listen() throws IOException {
		System.out.println("server start.");
		
		while(true) {
			//
			keys = this.selector.select();
			if (keys > 0)  {
				Iterator it = this.selector.selectedKeys().iterator();		
				while (it.hasNext()) {
					SelectionKey key = (SelectionKey) it.next();
					it.remove();
					// 是否完成套接字连接
					if (key.isAcceptable()) {
						serverChannel = (ServerSocketChannel) key.channel();
						
						SocketChannel channel = serverChannel.accept();
						channel.configureBlocking(false);
						
						channel.write(ByteBuffer.wrap(new String("Hello Client.").getBytes()));
						channel.register(selector, SelectionKey.OP_READ);
					} else if (key.isReadable()) {
						// read
						SocketChannel channel = (SocketChannel) key.channel();
						ByteBuffer buffer = ByteBuffer.allocate(1024);
						int length = channel.read(buffer);
						String msg = "server receive msg:" + new String(buffer.array(), 0, length);
						System.out.println(msg);
					}
				}
				
			} else {
				
			}
		}
	}

}

以上是关于java中NIO的selector的主要内容,如果未能解决你的问题,请参考以下文章

Java NIO 的前生今世 之四 NIO Selector 详解

(四:NIO系列) Java NIO Selector

不使用localhost时,Java NIO Selector不起作用

Java NIO Selector

java中NIO的selector

Java NIO Selector 的使用