AIO网络通信编程

Java4中开始的NIO虽然提供了非阻塞的IO方法,但是IO操作还是同步的,即业务线程必须等到IO操作准备好再进行其他操作。

在 Java 7 中又引入了 NIO 的改进版 NIO 2.0,NIO 2.0 的异步套接字通道是真正的异步非阻塞I/O,它对应UNIX网络编程中的事件驱动I/O(AIO),它不需要通过多路复用器(Selector)对注册的通道进行轮询操作即可实现异步读写,从而简化了NIO的编程模型。

我们再将之前的请求时间的demo再通过AIO进行重写:

服务端主程序入口:

package com.servertest;

import java.io.IOException;

public class TimeServerTest {

	public static void main(String[] args) throws IOException {
		int port = 8888;
		AsyncTimeServerHandler timeServer = new AsyncTimeServerHandler(port); 
		
		// 通过一个独立的I/O线程创建异步时间服务器客户端handler,在实际的项目中,不需要独立的线程
		new Thread(timeServer, "AIO-AsyncTirneServerHandler-O0l").start();
	}
}

用来接收客户端连接的AsyncTimeServerHandler类:

package com.servertest;

import java.net.InetSocketAddress;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.util.concurrent.CountDownLatch;

public class AsyncTimeServerHandler implements Runnable {

	private int port;
	CountDownLatch latch;
	AsynchronousServerSocketChannel asynchronousServerSocketChannel;
	
	public AsyncTimeServerHandler(int port) {
		// TODO Auto-generated constructor stub
		this.port = port;
		try {
			// 创建异步服务端通道
			asynchronousServerSocketChannel = AsynchronousServerSocketChannel.open();
			// 绑定监听端口
			asynchronousServerSocketChannel.bind(new InetSocketAddress(port));
			System.out.println("The time server is start in port: " + port);
		}catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
	}
	
	@Override
	public void run() {
		// TODO Auto-generated method stub
		latch = new CountDownLatch(1);
		// 接受客户端连接
		doAccept();
		try {
			latch.await();//让线程在此阻塞,防止服务端执行完毕退出
		}catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
	}
	
	public void doAccept() {
		// AcceptCompletionHandler对象用于接收accept操作成功的通知消息
		asynchronousServerSocketChannel.accept(this, new AcceptCompletionHandler());
	}
	
}

再创建一个AcceptCompletionHandler类来接收新的客户端连接:

package com.servertest;

import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;

public class AcceptCompletionHandler implements CompletionHandler<AsynchronousSocketChannel, AsyncTimeServerHandler>{

	@Override
	public void completed(AsynchronousSocketChannel result, AsyncTimeServerHandler attachment) {
		// 每当接收一个客户端读连接成功后,再异步接收新客户端连接
		attachment.asynchronousServerSocketChannel.accept(attachment, this);
		// 创建缓存,用于接收客户端的请求消息
		ByteBuffer buffer = ByteBuffer.allocate(1024);
		// 进行异步读操作
		result.read(buffer, buffer, new ReadCompletionHandler(result));
	}

	@Override
	public void failed(Throwable exc, AsyncTimeServerHandler attachment) {
		// TODO Auto-generated method stub
		exc.printStackTrace();
		attachment.latch.countDown();
	}
	
}

解析请求消息并返回响应的ReadCompletionHandler类:

package com.servertest;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;

public class ReadCompletionHandler implements CompletionHandler<Integer, ByteBuffer>{

	private AsynchronousSocketChannel channel;
	
	public ReadCompletionHandler(AsynchronousSocketChannel channel) {
		// TODO Auto-generated constructor stub
		if (this.channel == null) {
			this.channel = channel;
		}
	}
	
	@Override
	public void completed(Integer result, ByteBuffer attachment) {
		// TODO Auto-generated method stub
		attachment.flip();
		byte[] body = new byte[attachment.remaining()];
		attachment.get(body);
		try {
			String req = new String(body, "UTF-8");
			System.out.println("The time server receive order : " + req);
			String currentTime = "QUERY TIME ORDER".equalsIgnoreCase(req) ? new java.util.Date(
					System.currentTimeMillis()).toString() : "BAD ORDER";
			doWrite(currentTime);
		}catch (Exception e) {
			// TODO: handle exception
		}
	}
	
	public void doWrite(String currentTime) {
		if (currentTime != null && currentTime.length() > 0) {
			byte[] bytes = (currentTime).getBytes();
			ByteBuffer writeBuffer = ByteBuffer.allocate(1024);
			writeBuffer.put(bytes);
			writeBuffer.flip();
			channel.write(writeBuffer, writeBuffer, new CompletionHandler<Integer, ByteBuffer>() {

				@Override
				public void completed(Integer result, ByteBuffer buffer) {
					// 如果没有发送完成,继续发送
					if (buffer.hasRemaining()) {
						channel.write(buffer, buffer, this);
					}
				}

				@Override
				public void failed(Throwable exc, ByteBuffer attachment) {
					// TODO Auto-generated method stub
					try {
						channel.close();
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			});
		}
	}

	@Override
	public void failed(Throwable exc, ByteBuffer attachment) {
		// TODO Auto-generated method stub
		try {
			this.channel.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
}

客户端主程序入口:

package com.clienttest;

public class TimeClientTest {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int port = 8888;
		
		// 通过一个独立的I/O线程创建异步时间服务器客户端handler,在实际的项目中,不需要独立的线程
		new Thread(new AsyncTimeClientHandler("127.0.0.1", port), "AIO-AsyncTimeClientHandler-001").start();
	}

}

客户端处理类:

package com.clienttest;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.util.concurrent.CountDownLatch;

public class AsyncTimeClientHandler implements CompletionHandler<Void, AsyncTimeClientHandler>, Runnable{
	
	private AsynchronousSocketChannel client;
	private String host;
	private int port;
	private CountDownLatch latch;
	
	public AsyncTimeClientHandler(String host, int port) {
		// TODO Auto-generated constructor stub
		this.host = host;
		this.port = port;
		try {
			// 创建异步客户端通道
			client = AsynchronousSocketChannel.open();
		}catch (IOException e) {
			// TODO: handle exception
			e.printStackTrace();	
		}
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		latch = new CountDownLatch(1);
		// 与服务端创建连接
		client.connect(new InetSocketAddress(host, port), this, this);
		try {
			latch.await();
		}catch (InterruptedException e) {
			// TODO: handle exception
			e.printStackTrace();
		}
		try {
			client.close();
		}catch (IOException e) {
			// TODO: handle exception
			e.printStackTrace();
		}
	}

	@Override
	public void completed(Void result, AsyncTimeClientHandler attachment) {
		// TODO Auto-generated method stub
		byte[] req = "QUERY TIME ORDER".getBytes();
		ByteBuffer writeBuffer = ByteBuffer.allocate(req.length);
		writeBuffer.put(req);
		writeBuffer.flip();
		client.write(writeBuffer, writeBuffer, new CompletionHandler<Integer, ByteBuffer>() {

			@Override
			public void completed(Integer result, ByteBuffer buffer) {
				// TODO Auto-generated method stub
				if (buffer.hasRemaining()) {
					client.write(buffer, buffer, this);
				}else {
					ByteBuffer readBuffer = ByteBuffer.allocate(1024);
					client.read(readBuffer, readBuffer, new CompletionHandler<Integer, ByteBuffer>() {

						@Override
						public void completed(Integer result, ByteBuffer buffer) {
							// TODO Auto-generated method stub
							buffer.flip();
							byte[] bytes = new byte[buffer.remaining()];
							buffer.get(bytes);
							String body;
							try {
								body = new String(bytes, "UTF-8");
								System.out.println("Now is : " + body);
								latch.countDown();
							}catch (Exception e) {
								// TODO: handle exception
								e.printStackTrace();
							}
						}

						@Override
						public void failed(Throwable exc, ByteBuffer attachment) {
							// TODO Auto-generated method stub
							try {
								client.close();
								latch.countDown();
							} catch (IOException e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							}
						}
					
					});
				}
			}

			@Override
			public void failed(Throwable exc, ByteBuffer attachment) {
				// TODO Auto-generated method stub
				try {
					client.close();
					latch.countDown();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			
		});
	}

	@Override
	public void failed(Throwable exc, AsyncTimeClientHandler attachment) {
		// TODO Auto-generated method stub
		exc.printStackTrace();
		try {
			client.close();
			latch.countDown();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值