非阻塞模式与选择器搭配会工作的更好,通过将一或多个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(); }