JAVA nio 简单使用

nio 模拟客户端和服务器互相通讯--传输一个int值,并且不断的+1;
服务器,单线程

public class Server {
	public static void main(String[] args) {
		try {
			ServerSocketChannel server=ServerSocketChannel.open().bind(new InetSocketAddress(8881));
			server.configureBlocking(false);
			Selector selector=Selector.open();
			server.register(selector,SelectionKey.OP_ACCEPT);
			for(;;) {
				selector.select();
				Set<SelectionKey> keys = selector.selectedKeys();
				Iterator<SelectionKey> iterator = keys.iterator();
				while(iterator.hasNext()) {
					SelectionKey next = iterator.next();
					if(next.isAcceptable()) {
						acceptHandle(next, selector);
					}
					if (next.isReadable()) {
						doRead(next, selector);
					}
					iterator.remove();
				}
				Thread.sleep(2000);
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	public static void acceptHandle(SelectionKey key,Selector selector) throws IOException {
		ServerSocketChannel serverShannel =(ServerSocketChannel) key.channel();
		SocketChannel channel = serverShannel.accept();
		channel.configureBlocking(false);
		channel.register(selector, SelectionKey.OP_READ,ByteBuffer.allocate(1024));
	}
	public static  void doRead(SelectionKey key,Selector selector) throws IOException {
		SocketChannel socketChannel = (SocketChannel) key.channel();
		ByteBuffer buffer =(ByteBuffer) key.attachment();
		buffer.clear();
		int read = socketChannel.read(buffer);
		int msg=buffer.getInt(0);
		System.out.println("服务器收到客户端"+socketChannel.getLocalAddress()+"  "+msg);
		buffer.rewind();
		buffer.putInt(msg+1);
		buffer.flip();
		socketChannel.write(buffer);
		//buffer.clear();
	}
}

服务器,多线程

public class Server {
	private static ExecutorService executorService = Executors.newFixedThreadPool(4);//指定线程数大小
	public static void main(String[] args) {
		try {
			ServerSocketChannel server=ServerSocketChannel.open().bind(new InetSocketAddress(8881));
			server.configureBlocking(false);
			Selector selector=Selector.open();
			server.register(selector,SelectionKey.OP_ACCEPT);
			for(;;) {
				selector.select();
				Set<SelectionKey> keys = selector.selectedKeys();
				Iterator<SelectionKey> iterator = keys.iterator();
				while(iterator.hasNext()) {
					SelectionKey next = iterator.next();
					if(next.isAcceptable()) {
						acceptHandle(next, selector);
					}
					if (next.isReadable()) {
						executorService.submit(new Runnable() {//调用多线程,,这样子的话就是 accept 一个线程,read,write一个线程
							@Override
							public void run() {
								// TODO Auto-generated method stub
								try {
									doRead(next, selector);
								} catch (IOException e) {
									// TODO Auto-generated catch block
									e.printStackTrace();
								}
							}
						});
					}
					iterator.remove();
				}
				Thread.sleep(2000);
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	public static void acceptHandle(SelectionKey key,Selector selector) throws IOException {
		ServerSocketChannel serverShannel =(ServerSocketChannel) key.channel();
		SocketChannel channel = serverShannel.accept();
		channel.configureBlocking(false);
		channel.register(selector, SelectionKey.OP_READ,ByteBuffer.allocate(1024));
	}
	public static  void doRead(SelectionKey key,Selector selector) throws IOException {
		SocketChannel socketChannel = (SocketChannel) key.channel();
		ByteBuffer buffer =(ByteBuffer) key.attachment();
		buffer.clear();
		int read = socketChannel.read(buffer);
		int msg=buffer.getInt(0);
		System.out.println(Thread.currentThread().getName()+" 服务器收到客户端"+socketChannel.getLocalAddress()+"  "+msg);
		buffer.rewind();
		buffer.putInt(msg+1);
		buffer.flip();
		socketChannel.write(buffer);
		//buffer.clear();
	}
}

客户端

public class Client {
	public static void main(String[] args) {
		try(SocketChannel channel=SocketChannel.open();
			Selector selector=Selector.open();
				) {
			channel.configureBlocking(false);
			if(!channel.connect(new InetSocketAddress("127.0.0.1", 8881))) {
				while(!channel.finishConnect()) {};
				System.out.println("连接到服务器");
			}
			
			ByteBuffer buffer = ByteBuffer.allocate(1024);
			buffer.putInt(1);
			buffer.flip();
			channel.write(buffer);
			channel.register(selector, SelectionKey.OP_READ,buffer);
			for(;;) {
				selector.select();
				Set<SelectionKey> keys = selector.selectedKeys();
				Iterator<SelectionKey> iterator = keys.iterator();
				while(iterator.hasNext()) {
					SelectionKey next = iterator.next();
					if(next.isReadable()) {
						doRead(next,selector);
					}
					iterator.remove();
				}
				Thread.sleep(2000);
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	public static void doRead(SelectionKey key,Selector selector) throws IOException {
		SocketChannel socketChannel = (SocketChannel) key.channel();
		ByteBuffer buffer =(ByteBuffer) key.attachment();
		buffer.clear();
		socketChannel.read(buffer);
		int msg=buffer.getInt(0);
		System.out.println("客户端收到服务器返回的信息"+socketChannel.getLocalAddress()+"  "+msg);
		buffer.putInt(0,msg+1);
		buffer.flip();
		socketChannel.write(buffer);
		
	}
	
}

**ByteBuffer 是一个缓存区,用来保存用户要传输的数据,里面的读写方法是有一个 position ,limiet , capacity。 + position类似一个指针,可以理解为记事本里的光标。代表了一个位置 + limit是指针位置的最大限制, + capacity指的是容量 就是ByteBuffer的大小。 ByteBuffer 几个方法 clear(), flip(),rewind()等,都是对上面3个值进行操作。 而调用ChannelSocket的read() ,write()方法,传入一个ByteBuffer。都是根据传入的ByteBuffer里的3个值,进行读写。 例如: ``` ByteBuffer buf=new ByteBuffer(1024); //position=0,limit=1024,capacity=1024 buf.putInt(1);//在position为0的位置放入一个int,int为4字节,放完后。position=4; channel.write(buf);//这里socket去传输这个buffer,这里也是从position=4的地方开始写的,一直写到limit。然后相当于没传数据 ```
posted @ 2019-10-05 22:11  你还未发现  阅读(661)  评论(0编辑  收藏  举报