Java Nio 整理

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;
    }


client:

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)

结果抛出异常,原因不详,待查明,路过的大虾知道可以指点下



你可能感兴趣的:(java,nio)