java Nio 平时开发工作中基本不会用到,因为工作偏向web那块.陆陆续续了解过NIo的知识,跑过一些demo,但是印象就是不深刻,应该是理解的不够
深刻导致的,今天花了点时间去看了下源码,没怎么懂,又写了一遍demo,比以前稍微理解点。先贴上demo加深印象,源码在慢慢理解。
demo包含server,client两部分
server:
package com.my.Niotest; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; 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 ServerTest { public static void main(String[] args) throws Exception { server(); } public static void server(){ ServerSocketChannel channel=null; try{ Selector selector=Selector.open(); for(int i=0;i<10;i++ ){ channel=ServerSocketChannel.open(); channel.configureBlocking(false); channel.socket().setReuseAddress(true); channel.bind(new InetSocketAddress(802+i)); channel.register(selector, SelectionKey.OP_ACCEPT,i); } while(true){ if(selector.select()>0){ Set<SelectionKey> sets=selector.selectedKeys(); Iterator<SelectionKey> keys=sets.iterator(); while(keys.hasNext()){ SelectionKey key=keys.next(); keys.remove(); InetSocketAddress add=(InetSocketAddress) ((ServerSocketChannel) key.channel()).getLocalAddress(); System.out.println(add.getPort()); SocketChannel schannel=((ServerSocketChannel) key.channel()).accept(); ByteBuffer buf=ByteBuffer.allocate(1024); int len=0; ByteArrayOutputStream output=new ByteArrayOutputStream(); while((len=schannel.read(buf))!=-1){ output.write(buf.array(),0, len); } String result=new String(output.toByteArray()); System.out.println(result); } } } }catch(Exception e){ e.printStackTrace(); }finally{ if(channel!=null){ try { channel.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
总结:
1.一个selector 可以被多个channel注册
2.ServerSocketChannel 的validOps 只有 SelectionKey.OP_ACCEPT, 类似channel.register(selector, SelectionKey.OP_CONNECT | SelectionKey.OP_READ i)是无效的,
原因只可意会。
3.selector.select()>0 判断有可以接收的channel
4.因为selector可以注册多个channel,所以selector.selectedKeys()方法返回那些接受就绪的channel(SelectionKey.OP_ACCEPT),
selectionKey的实现者SelectionKeyImpl源码构造方法如下:
SelectionKeyImpl(SelChImpl ch, SelectorImpl sel) { channel = ch; selector = sel; }
package com.my.Niotest; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; public class ClientTest { public static void main(String[] args) throws Exception { for(int i=0;i<10;i++){ final int j=i; new Runnable() { @Override public void run() { client(j); } }.run(); } } public static void client(int j) { SocketChannel channel=null; try { channel = SocketChannel.open(); channel.connect(new InetSocketAddress(802+j)); channel.write(ByteBuffer.wrap((("hi nio")+j).getBytes())); channel.socket().shutdownOutput(); } catch (IOException e) { e.printStackTrace(); }finally{ try { channel.close(); } catch (IOException e) { e.printStackTrace(); } } } }
channel.configureBlocking(false)
结果抛出异常,原因不详,待查明,路过的大虾知道可以指点下