非阻塞模式與選擇器搭配會工作的更好,通過將一或多個SocketChannel注冊到Selector,可以詢問選擇器哪個通道已經准備好了讀取,寫入等
上面已經分別介紹過SocketChannel和Selector 但是非阻塞模式與選擇器搭配工作的代碼沒有整合。
如下就是非阻塞模式使用選擇器的代碼:
private static final int TIMEOUT = 3000; private static final int BUF_SIZE=1024; private static final int PORT = 9999; @Test public void test1() throws IOException, InterruptedException { test("I'm 1st information from client"); } @Test public void test3() throws IOException, InterruptedException { test("I'm 2st information from client"); } public void test(String info) throws IOException, InterruptedException { SocketChannel socketChannel = SocketChannel.open(); //設置為NIO socketChannel.configureBlocking(false); socketChannel.connect(new InetSocketAddress("localhost", PORT)); ByteBuffer buf = ByteBuffer.allocate(BUF_SIZE); if(socketChannel.finishConnect()) { while(true) { TimeUnit.SECONDS.sleep(1); buf.clear(); buf.put(info.getBytes()); buf.flip(); while(buf.hasRemaining()){ socketChannel.write(buf); } } } } @Test public void test2() throws IOException { Selector selector = Selector.open(); ServerSocketChannel ssc = ServerSocketChannel.open(); ssc.socket().bind(new InetSocketAddress(PORT)); ssc.configureBlocking(false); // int interestSet = SelectionKey.OP_READ & SelectionKey.OP_WRITE & SelectionKey.OP_ACCEPT; ssc.register(selector,SelectionKey.OP_ACCEPT ); while(true){ if(selector.select(TIMEOUT) == 0){ System.out.println("=="); continue; } Iterator<SelectionKey> iter = selector.selectedKeys().iterator(); while(iter.hasNext()){ SelectionKey key = iter.next(); if(key.isAcceptable()){ handleAccept(key); } if(key.isReadable()){ handleRead(key); } if(key.isWritable() && key.isValid()){ handleWrite(key); } if(key.isConnectable()){ System.out.println("isConnectable = true"); } iter.remove(); } } } public static void handleWrite(SelectionKey key) throws IOException{ ByteBuffer buf = (ByteBuffer)key.attachment(); buf.flip(); SocketChannel sc = (SocketChannel) key.channel(); while(buf.hasRemaining()){ sc.write(buf); } buf.compact(); }