import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.util.concurrent.TimeUnit;
public class TimeServer {
private int port;
private AsynchronousServerSocketChannel socketChannel;
public AsynchronousServerSocketChannel getSocketChannel() {
return socketChannel;
}
public static void main(String[] args) throws InterruptedException {
new TimeServer(8090);
//模拟主线程等待
TimeUnit.SECONDS.sleep(Long.MAX_VALUE);
}
public TimeServer(int port){
this.port = port;
try {
init(port);
}catch (Exception e){
e.printStackTrace();
}
}
private void init(int port) throws IOException {
//打开异步socket服务端
socketChannel = AsynchronousServerSocketChannel.open();
//板顶监听端口,设置最大连接数
socketChannel.bind(new InetSocketAddress(port),1024);
//这里绑定TimeHandler ,当有新的客户端接入成功后会回调TimeHandler的completed
// 在这个completed方法中要继续调用accept方法,继续接收其它请求,this就是TimeServer本身
socketChannel.accept(this,new TimeHandler());
System.out.println("server start");
}
}
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
public class TimeHandler implements CompletionHandler<AsynchronousSocketChannel,TimeServer> {
@Override
public void completed(AsynchronousSocketChannel result, TimeServer attachment) {
// 在这个completed方法中要继续调用accept方法,继续接收其它请求,形成类似链式调用
attachment.getSocketChannel().accept(attachment,this);
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
//调用异步读取的方法,参数一:接收缓冲区 参数二:附件参数 参数三:回调处理类
//当读取完成客户端发送过来的信息,回调ReadCompletionHandler的方法
result.read(byteBuffer,byteBuffer,new ReadCompletionHandler(result));
}
@Override
public void failed(Throwable exc, TimeServer attachment) {
exc.printStackTrace();
System.out.println("failed");
}
}
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) {
this.channel = channel;
}
@Override
public void completed(Integer result, ByteBuffer attachment) {
try {
//获取并打印客户端发送过来的消息
attachment.flip();
byte[] bytes = new byte[attachment.remaining()];
attachment.get(bytes);
String msg = new String(bytes, "utf-8");
System.out.println("get msg from client:"+msg);
//服务端响应客户端写回消息
doWrite(System.currentTimeMillis()+"server send msg");
}catch (Exception e){
e.printStackTrace();
}
}
private void doWrite(String str) {
byte[] bytes = str.getBytes();
ByteBuffer writeBuff = ByteBuffer.allocate(bytes.length);
writeBuff.put(bytes);
writeBuff.flip();
//将消息写到缓冲区进行发送,写完成后回调方法
channel.write(writeBuff,writeBuff,new CompletionHandler<Integer, ByteBuffer>(){
@Override
public void completed(Integer result, ByteBuffer attachment) {
//没有发送完成,接续发送
if (attachment.hasRemaining()){
channel.write(attachment,attachment,this);
}
}
@Override
public void failed(Throwable exc, ByteBuffer attachment) {
close();
}
});
}
@Override
public void failed(Throwable exc, ByteBuffer attachment) {
close();
}
private void close(){
try {
if (channel != null)
channel.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.util.concurrent.TimeUnit;
public class AsyncTimerClient implements CompletionHandler<Void, AsyncTimerClient> {
private String host;
private int port;
private AsynchronousSocketChannel client;
public AsyncTimerClient(String host, int port) {
this.host = host;
this.port = port;
try {
//开启异步socket通道
client = AsynchronousSocketChannel.open();
//参数二:附件 参数三:处理器,实现CompletionHandler接口
client.connect(new InetSocketAddress(host,port),this,this);
System.out.println("client start");
} catch (IOException e) {
e.printStackTrace();
}
}
//当一个操作完成时进行回调,比如连接建立,收到消息等
@Override
public void completed(Void result, AsyncTimerClient attachment) {
byte[] bytes = "send time to server".getBytes();
ByteBuffer WriteBuffer = ByteBuffer.allocate(bytes.length);
WriteBuffer.put(bytes);
WriteBuffer.flip();
client.write(WriteBuffer, WriteBuffer, new CompletionHandler<Integer, ByteBuffer>() {
@Override
public void completed(Integer result, ByteBuffer attachment) {
//判断没有写完,继续写
if (attachment.hasRemaining()){
client.write(attachment,attachment,this);
}else {
//读取客户端返回的消息
ByteBuffer readBuff = ByteBuffer.allocate(1024);
client.read(readBuff, readBuff, new CompletionHandler<Integer, ByteBuffer>() {
@Override
public void completed(Integer result, ByteBuffer attachment) {
attachment.flip();
byte[] readByte = new byte[attachment.remaining()];
attachment.get(readByte);
String msg = null;
try {
msg = new String(readByte, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
System.out.println(" msg from server:"+msg);
}
@Override
public void failed(Throwable exc, ByteBuffer attachment) {
close();
}
});
}
}
@Override
public void failed(Throwable exc, ByteBuffer attachment) {
close();
}
});
}
@Override
public void failed(Throwable exc, AsyncTimerClient attachment) {
close();
}
private void close(){
try {
if (client != null)
client.close();
}catch (IOException e){
e.printStackTrace();
}
}
public static void main(String[] args) throws InterruptedException {
new AsyncTimerClient("127.0.0.1",8090);
TimeUnit.SECONDS.sleep(Long.MAX_VALUE);
}
}
JDK底层通过线程池ThreadPoolExecutor来执行aio的异步回调,最终回调通知类由 AsynchronousChannelGroupImpl实现。
JAVA AIO框架在windows下使用windows IOCP技术,在Linux下使用epoll多路复用IO技术模拟异步IO