原理:
运用reactor模式
Selector是核心-分发器A multiplexor of SelectableChannel objects。
能检测任意个注册过的channel上的事件,并分发事件,内部实现不用考虑,封装的好处。
client没必要用NIO,使用http://luckywnj.iteye.com/blog/1744283中的client
server,
需要多线程的么?workthread?如何写?
/** * @author timeriver.wang * @version 2013-1-7 11:50:33 PM */ public class NIOServer { public static void main(String[] args) throws Exception { ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); serverSocketChannel.socket().bind(new InetSocketAddress(8899)); serverSocketChannel.configureBlocking(false); Selector selector = Selector.open(); serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); Charset charset = Charset.forName("UTF-8"); CharsetDecoder decoder = charset.newDecoder(); CharsetEncoder encoder = charset.newEncoder(); ByteBuffer clientBuffer = ByteBuffer.allocate(1024); while (true) { // 貌似两个client同时连,返回也是1?在select处阻塞,这样避免线程卡死耗尽资源? // int sel = selector.select(); int sel = selector.select(3000); if (sel == 0) { continue; } Set<SelectionKey> set = selector.selectedKeys(); System.out.println(set.size()); Iterator<SelectionKey> keyIter = set.iterator(); while (keyIter.hasNext()) { SelectionKey key = keyIter.next(); System.out.println(key); // channel is ready to accept a new socket connection if (key.isAcceptable()) { SocketChannel serverChannel = ((ServerSocketChannel) key.channel()).accept(); // 为serverChannel再设置一次否则,java.nio.channels.IllegalBlockingModeException, serverChannel.configureBlocking(false); SelectionKey skey = serverChannel.register(key.selector(),SelectionKey.OP_READ); System.out.println("acceptable: serverChannel="+serverChannel+",skey="+skey); }else if (key.isReadable()) {// channel is ready for reading SocketChannel serverChannel = (SocketChannel) key.channel(); clientBuffer.clear(); long bytesRead = serverChannel.read(clientBuffer); if (bytesRead == -1) { serverChannel.close(); } else { clientBuffer.flip(); String receivedMsg = decoder.decode(clientBuffer).toString(); System.out.println("receive msg: " + receivedMsg); SelectionKey skey = serverChannel.register(selector,SelectionKey.OP_WRITE); System.out.println("readable "+skey); skey.attach(receivedMsg); } } else if (key.isWritable()) { //channel is ready for writing SocketChannel serverChannel = (SocketChannel) key.channel(); String sendMsg = (String) key.attachment(); ByteBuffer block = encoder.encode(CharBuffer.wrap("Hello !"+sendMsg)); serverChannel.write(block); SelectionKey skey = serverChannel.register(key.selector(),SelectionKey.OP_READ); System.out.println("write "+skey); } keyIter.remove(); } } } }