鉴于网上关于java7之AIO(只能在windows 操作系统下才能实现功能)实现的实例少而且讲述的不够详细,特此写这篇博客供大家借鉴,希望能帮助和我一样苦逼的java程序员们,也希望高手能指出博客描述不当之处
废话少说,直接进入主题:先贴段服务器代码,代码没进行封装,可能比较乱
public class AIOServer {
public final static int PORT = 9888; //端口号
private AsynchronousServerSocketChannel server; //此类相当一一个服务器的SOCKET,不过它的实现是异步通信形式
public Map<String, List<AsynchronousSocketChannel>> map=
new HashMap<String, List<AsynchronousSocketChannel>>();
public AIOServer() throws IOException {
// AsynchronousChannelGroup group = AsynchronousChannelGroup.withCachedThreadPool(Executors.newCachedThreadPool(), 1);
// server = AsynchronousServerSocketChannel.open(group);
// //通过setOption配置Socket
// server.setOption(StandardSocketOptions.SO_REUSEADDR, true);
// server.setOption(StandardSocketOptions.SO_RCVBUF, 16 * 1024);
// //绑定到指定的主机,端口
// server.bind(new InetSocketAddress("写一个Ip地址", PORT));
//上面注释掉的写法,经我测试,会报IO异常
server = AsynchronousServerSocketChannel.open().bind(
new InetSocketAddress("192.168.1.100",PORT));
}
public void startWithCompletionHandler() throws InterruptedException,
ExecutionException, TimeoutException {
System.out.println("Server listen on " + PORT);
/*****************************************************
* 主要功能:注册事件和事件完成后的处理器
* 实现原理:当一有用户连接到服务器时,会调用accept方法,
* 此方法是一个非阻塞方法并和一个完成端口(即处理器-CompletionHandler)进行绑定的方法
* 当用户连接成功时,完成端口会自动调用completed方法,这步由操作系统完成
* 要实现能连接多用户,必须在completed方法中在循环调用一次accept方法
* 代码如下:server.accept(null, this);
* 关于IOCP的详细实现原理参见C++中的IOCP
*****************************************************/
server.accept(null,new CompletionHandler<AsynchronousSocketChannel, Object>() {
//ByteBuffer:接收数据的缓冲区,这里初始化大小为65535
ByteBuffer buffer = ByteBuffer.allocate(65535);
@Override
public void completed(AsynchronousSocketChannel result,Object attachment) {
//AsynchronousSocketChannel相当唯一标示客户的socket
//这里需要加个final关键字才能让SocketChannel对象在方法read中可见
final AsynchronousSocketChannel SocketChannel=result;
//再次向处理器投递一个连接请求
server.accept(null, this);
try {
//清空缓冲区,这步不能省
buffer.clear();
result.read(buffer, null, new CompletionHandler<Integer, Object>() {
@Override
public void completed(Integer result1,Object result2) {
System.out.println("result1:"+result1);
if(result1==-1){
//这里面可进行对失去连接的客户端进行删除操作
}
if(result1!=-1){
buffer.flip();
//接收到的数据缓冲区转字节数,此后可对这个数组进行操作
}
//完成接收操作之后,必须清空缓冲区,不然会出现死循环
buffer.clear();
//再次向处理器投递一个接收数据请求
SocketChannel.read(buffer, null, this);
}
@Override
public void failed(Throwable exc,Object result2) {
exc.printStackTrace();
System.out.println("failed: " + exc);
//完成接收操作之后,必须清空缓冲区,不然会出现死循环
buffer.clear();
//再次向处理器投递一个接收数据请求
SocketChannel.read(buffer, null, this);
}
});
}catch (Exception e) {
e.printStackTrace();
}finally {
}
}
@Override
public void failed(Throwable exc, Object attachment) {
exc.printStackTrace();
System.out.println("failed: " + exc);
//再次向处理器投递一个连接请求
server.accept(null, this);
}
});
// 这里必须 保证主线程的存活
System.in.read();
}
public static void main(String args[]) throws Exception {
new AIOServer().startWithCompletionHandler();
}
}
注:置于服务器往客户端发送数据操作,可把连接成功之后的客户端AsynchronousSocketChannel result保存到一个List集合中,再在接收用户数据操作中另开一个线程,占门处理发送事件,也开独立开一个线程去监控是否有客户端发送数据过来,然后对list进行遍历群发,置于实现分组发送,描述比较麻烦,就不详述,发送数据的方法是result.write();write有好几种重载方式,详细见官网api,api地址http://docs.oracle.com/javase/7/docs/api/。