io-nio-socket步步为营(三)NIO

原理:

运用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();
			}
		}
	}
}

猜你喜欢

转载自luckywnj.iteye.com/blog/1759310
今日推荐