Java NIO 简单事件响应实现

com.nio.Server

package com.nio;

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.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;


public class Server {
	private Selector selector = null;
	
	public Server() throws IOException{
		// register the server
		ServerSocketChannel ssc = ServerSocketChannel.open(); 
		ssc.configureBlocking(false);
		int port = 8080;
		InetSocketAddress endpoint = new InetSocketAddress(port );
		ssc.socket().bind(endpoint);
		selector = Selector.open();
		ssc.register(selector, SelectionKey.OP_ACCEPT);
	}
	
	public void start() throws IOException{
		while(true){
			int num = selector.select();
			
			if(num>0){
				Set<SelectionKey> selectionKeySet = selector.selectedKeys();
				Iterator<SelectionKey> iterator = selectionKeySet.iterator();
				while(iterator.hasNext()){
					SelectionKey key = iterator.next();
					iterator.remove();// must remove it
					
					if (key.isAcceptable()) {
						ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key.channel();
						SocketChannel sc = serverSocketChannel.accept();
						sc.configureBlocking(false);
						sc.register(selector, SelectionKey.OP_READ);
						
					}else if (key.isReadable()) {
						System.out.println("do read ...");
						SocketChannel sc = (SocketChannel) key.channel();
						sc.register(selector, SelectionKey.OP_WRITE);
						
					}else if (key.isWritable()) {
						System.out.println("do write ...");
						SocketChannel sc = (SocketChannel) key.channel();
						sc.close();
						key.cancel();
					}
				}
			}
		}
	}
	
	
	public static void main(String[] args) throws Exception {
		new Server().start();
	}

}

com.nio.Client

package com.nio;

import java.io.IOException;
import java.net.Socket;

public class Client {
	public static void main(String[] args) throws IOException{
		System.out.println("client start ... ");
		
		Socket socket = new Socket("localhost",8080);
		
		socket.close();
		
		System.out.println("client end ... ");
	}
}

 

Note:

1. 在使用Iterator迭代SelectionKey的后,必须调用Iterator.remove(). 因为select()只会向selector所关联的键集合中添加元素,如果不移除每个处理过的键,它就会在下次select()方法时仍然保留在集合中。

2. 不要轻易使用SelectionKey.cancel(). cancel 会终止selector 和 key关联的Channel的联系。

 

猜你喜欢

转载自antlove.iteye.com/blog/2102013
今日推荐