1.写在前面
十年前就有高人在Windows上面用VC++写的高并发Tcp服务器程序,运用IOCP,异步Socket实现,可谓运用的淋漓尽致,即便是.Net中最新的Socket异步通信也只可能达到了这个的水平,而Java7中AsynchronousServerSocket还停留在.Net中Begin/End模式的时代,或许是专业领域不同吧,通用的软件库不会在某一个领域过于深入。
当然.Net与Java比C++上面实现,容易多了。
那个作者要是没有搞错的话就是他了: http://blog.csdn.net/sodme
2.基本思路
本人学识有限,多多指正线程池执行所有的任务,线程池相对与一个线程维护一个连接可以减少线程本身对资源的消耗,如线程切换时CPU的消耗,线程本身内存占用。异步IO操作就是,IO操作的发起与结束是分离的,发起IO操作以后中间不需要等待IO操作的完成,最好的处理方式就是是提交IO操作到线程池并且传递一个完成后的用于通知的完成方法。.Net中begin/end模式就是这样子的,Java中AsynchonousServerSocketChannel也是这样的。begin/end模式通常简单用法,begin被第一次在初始化地方发起以后,当end响应以后,在end结尾处继续begin,更加开发的方式是,一次发起较多begin,然后用列表来管理,性能可能会更好,但是收到数据的顺序可能需要维护了。本文所述是单次begin/end方式。
3.代码示例
文件有两份
AsynchonousSocketClient.java
package FirstExercise;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousSocketChannel;
public class AsynchronousSocketClient {
private final AsynchronousSocketChannel asynchronousSocketChannel;
private final String address;
private final ByteBuffer byteBuffer;
public AsynchronousSocketClient(String address, AsynchronousSocketChannel asynchronousSocketChannel) {
this.asynchronousSocketChannel = asynchronousSocketChannel;
this.address = address;
byteBuffer = ByteBuffer.allocateDirect(16 * 1024);
}
public AsynchronousSocketChannel getAsynchronousSocketChannel() {
return asynchronousSocketChannel;
}
public String getAddress() {
return address;
}
public ByteBuffer getByteBuffer() {
return byteBuffer;
}
}
AsynchonousSocketServer.java
package FirstExercise;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.net.StandardSocketOptions;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.util.concurrent.ConcurrentHashMap;
public class AsynchronousSocketService {
private final String host;
private final int port;
private AsynchronousServerSocketChannel asynchronousServerSocketChannel;
ConcurrentHashMap<String, AsynchronousSocketClient> clientMap;
public AsynchronousSocketService(String host, int port) {
this.host = host;
this.port = port;
clientMap = new ConcurrentHashMap<>();
}
public void start() {
try {
SocketAddress localAddress = new InetSocketAddress(host, port);
asynchronousServerSocketChannel = AsynchronousServerSocketChannel.open();
asynchronousServerSocketChannel.setOption(StandardSocketOptions.SO_REUSEADDR, true);
asynchronousServerSocketChannel.bind(localAddress, 100);
asynchronousServerSocketChannel.accept(null, new AcceptCompletionHandler());
System.out.println("Start AsynchronousSocketService " + localAddress);
} catch (IOException e) {
e.printStackTrace();
}
}
public void stop() {
try {
if (asynchronousServerSocketChannel != null) {
asynchronousServerSocketChannel.close();
asynchronousServerSocketChannel = null;
}
} catch (IOException e) {
e.printStackTrace();
}
clientMap.forEach((x, y) -> {
try {
if (y != null) y.getAsynchronousSocketChannel().close();
} catch (IOException e) {
e.printStackTrace();
}
});
clientMap.clear();
System.out.println("Stop AsynchronousSocketService");
}
class AcceptCompletionHandler implements CompletionHandler<AsynchronousSocketChannel, Object> {
@Override
public void completed(AsynchronousSocketChannel result, Object attachment) {
try {
AsynchronousSocketClient client = new AsynchronousSocketClient(
result.getRemoteAddress().toString(), result);
clientMap.put(client.getAddress(), client);
result.read(client.getByteBuffer(), client, new ReadCompletionHandler());
System.out.println("Accept Client\t\t" + client.getAddress());
asynchronousServerSocketChannel.accept(null, new AcceptCompletionHandler());
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void failed(Throwable exc, Object attachment) {
System.out.println("Accept Exception");
}
}
class ReadCompletionHandler implements CompletionHandler<Integer, Object> {
@Override
public void completed(Integer result, Object attachment) {
AsynchronousSocketClient client = (AsynchronousSocketClient) attachment;
AsynchronousSocketChannel channel = client.getAsynchronousSocketChannel();
ByteBuffer byteBuffer = client.getByteBuffer();
if (result <= 0) {
try {
channel.close();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("Close Client " + client.getAddress());
clientMap.remove(client.getAddress());
return;
}
System.out.printf("Read\t%d\tfrom\t%s\n", result, client.getAddress());
byteBuffer.flip();
channel.write(byteBuffer, client, new WriteCompletionHandler());
byteBuffer.clear();
channel.read(byteBuffer, client, new ReadCompletionHandler());
}
@Override
public void failed(Throwable exc, Object attachment) {
AsynchronousSocketClient client = (AsynchronousSocketClient) attachment;
System.out.printf("Read Exception %s\n", client.getAddress());
}
}
class WriteCompletionHandler implements CompletionHandler<Integer, Object> {
@Override
public void completed(Integer result, Object attachment) {
AsynchronousSocketClient client = (AsynchronousSocketClient) attachment;
System.out.printf("Write\t%d\tto\t\t%s\n", result, client.getAddress());
}
@Override
public void failed(Throwable exc, Object attachment) {
AsynchronousSocketClient client = (AsynchronousSocketClient) attachment;
System.out.printf("Write Exception %s\n", client.getAddress());
}
}
}