Java NIO2 -- AIO CompletionHandler

package com.xiuye.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.StandardSocketOptions;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.util.concurrent.ExecutionException;

public class NIO2_AIO_Server2 {

	private AsynchronousServerSocketChannel serverChannel;

	class ServerCompletionHandler implements CompletionHandler<AsynchronousSocketChannel, Void>{

		private AsynchronousServerSocketChannel serverChannel;
		private ByteBuffer buffer = ByteBuffer.allocateDirect(1024);
		private CharBuffer charBuffer;
		private CharsetDecoder decoder = Charset.defaultCharset().newDecoder();

		public ServerCompletionHandler(AsynchronousServerSocketChannel serverChannel) {
			this.serverChannel = serverChannel;
		}


		@Override
		public void completed(AsynchronousSocketChannel result, Void attachment) {

			//立即接收下一个请求,不停顿
			serverChannel.accept(null,this);
			try {
				while(result.read(buffer).get()!=-1){
					buffer.flip();
					charBuffer = decoder.decode(buffer);
					String request = charBuffer.toString().trim();
					System.out.println("Client Request MSG: "+request);
					ByteBuffer outBuffer = ByteBuffer.wrap("Request Received!".getBytes());
					result.write(outBuffer).get();
					if(buffer.hasRemaining()){
						buffer.compact();
					}
					else{
						buffer.clear();
					}
				}
			} catch (InterruptedException | ExecutionException e) {
				e.printStackTrace();
			} catch (CharacterCodingException e) {
				e.printStackTrace();
			}
			finally{
				try {
					result.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}

		}

		@Override
		public void failed(Throwable exc, Void attachment) {
			//立即接收下一个请求,不停顿
			serverChannel.accept(null,this);
			throw new RuntimeException("connection failed!");
		}

	}

	public void init() throws IOException{
		this.serverChannel = AsynchronousServerSocketChannel.open();
		if(serverChannel.isOpen()){
			serverChannel.setOption(StandardSocketOptions.SO_RCVBUF, 4*1024);
			serverChannel.setOption(StandardSocketOptions.SO_REUSEADDR, true);
			serverChannel.bind(new InetSocketAddress(8080));
		}else{
			throw new RuntimeException("Channel not opened!");
		}
	}

	public void start() throws InterruptedException{
		System.out.println("Wait for Client ...");
		this.serverChannel.accept(null,new ServerCompletionHandler(serverChannel));
		while(true){
			Thread.sleep(5000);
		}
	}


	public static void main(String[] args) throws IOException, InterruptedException{

		NIO2_AIO_Server2 server = new NIO2_AIO_Server2();

		server.init();
		server.start();

	}

}


package com.xiuye.nio;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.net.StandardSocketOptions;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.util.concurrent.ExecutionException;

public class NIO2_AIO_Client2 {

	class ClientCompletionHandler implements CompletionHandler<Void, Void>{

		private AsynchronousSocketChannel channel;
		private CharBuffer charBufferr = null;
		private CharsetDecoder decoder = Charset.defaultCharset().newDecoder();
		private BufferedReader clientInput = new BufferedReader(new InputStreamReader(System.in));

		public ClientCompletionHandler(AsynchronousSocketChannel channel) {
			this.channel = channel;
		}


		@Override
		public void completed(Void result, Void attachment) {

			System.out.println("Input Client Reuest:");
			String request;
			try {
				request = clientInput.readLine();
				channel.write(ByteBuffer.wrap(request.getBytes()));
				ByteBuffer buffer = ByteBuffer.allocateDirect(1024);
				while(channel.read(buffer).get() != -1){
					buffer.flip();
					charBufferr = decoder.decode(buffer);
					System.out.println(charBufferr.toString());
					if(buffer.hasRemaining()){
						buffer.compact();
					}
					else{
						buffer.clear();
					}
					request = clientInput.readLine();
					channel.write(ByteBuffer.wrap(request.getBytes())).get();
				}
			} catch (IOException e) {
				e.printStackTrace();
			} catch (InterruptedException e) {
				e.printStackTrace();
			} catch (ExecutionException e) {
				e.printStackTrace();
			}
			finally {
				try {
					channel.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}


		}

		@Override
		public void failed(Throwable exc, Void attachment) {
			throw  new  RuntimeException("channel not opened!");
		}

	}

	public void start() throws IOException, InterruptedException{
		AsynchronousSocketChannel channel = AsynchronousSocketChannel.open();
		if(channel.isOpen()){
			channel.setOption(StandardSocketOptions.SO_RCVBUF, 128*1024);
			channel.setOption(StandardSocketOptions.SO_SNDBUF, 128*1024);
			channel.setOption(StandardSocketOptions.SO_KEEPALIVE,true);
			channel.connect(new InetSocketAddress("127.0.0.1",8080),null,new ClientCompletionHandler(channel));
			while(true){
				Thread.sleep(5000);
			}
		}
		else{
			throw new RuntimeException("Channel not opened!");
		}
	}

	public static void main(String[] args) throws IOException, InterruptedException{
		NIO2_AIO_Client2 client = new NIO2_AIO_Client2();
		client.start();
	}

}



延伸:

IOCP 百度百科

Linux IO模式及 select、poll、epoll详解

It's just my prejudice:

1.不管什么I/O是同步还是异步,总要有一个执行I/O的操作(者),也许是系统(kernel)也许是用户进程,其实最终还是

System(kernel)完成(读写),那么I/O就会花时间,难道还会瞬移?

2.阻塞和非阻塞的上层应用,决定了其底层的实现意图(上层),但是底层还是会阻塞,比如读数据,归根到底,用户进程阻塞不阻塞,

都不能瞬间拿到数据,除非数据是"0"或者数据不重要尽管丢弃吧,系统(kernel)拿到了,用户进程才有,当然绕过系统(kernel),

能力强悍的用户进程就尽管去试试吧.

3.因为非阻塞和异步,感觉上,表面上,事实上,其确实可以在I/O未完成时候做其他事情,但仍然不能改变读数据花时间,难道还会瞬移?

这是一种策略或者方法,屏蔽了底层的过程,然而事实仍然存在,操作数据花时间.

4.即便它是异步非阻塞,也还是要check下数据 op end,不然代码怎么会有循环呢,只能说,你在循环内next step可以马上做其他事情,因为循环内的函数/方法不阻塞.

5.不管什么方法策略,主要目的解决资源开销,性能问题,资源复用是个好办法,上层开销大,底层开销小是个不错的选择.

All in all, 异步同步阻塞非阻塞 relative to "粒度大小".整个过程(包括底层过程)[针对I/O,数据重要要用]没有完美的彻底的异步非阻塞,因为其可以实现(包括底层)的方式决定了他们是相互包含的吧.

IOCP模型与网络编程

对异步的尝试





阅读更多
换一批

没有更多推荐了,返回首页