java 7之AIO对完成端口(IOCP)的实现

鉴于网上关于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/

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值