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 {
				
			}
		}
	}

}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值