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的联系。