zoukankan      html  css  js  c++  java
  • java核心学习(三十三) 网络编程---AIO实现异步Socket通信

      AIO需要操作系统的支持,在linux内核2.6版本中加入了对真正异步IO的支持,java从jdk1.7开始支持AIO

    核心类有AsynchronousSocketChannel 、AsynchronousServerSocketChannel、AsynchronousChannelGroup

      前两个个类是javaAIO为TCP通信提供的异步Channel。看名字就知道应该是干什么的了。

      创建AsynchronousServerSocketChannel的代码如下:    

    AsynchronousServerSocketChannel serverChannel = AsynchronousServerSocketChannel.open().bind(new InetSocketAddress(PORT));

      其中open()有一个重载方法,可以使用指定的AsynchronousChannelGroup来创建AsynchronousServerSocketChannel。

      AsynchronousChannelGroup是异步Channel的分组管理器,它可以实现资源共享。创建AsynchronousChannelGroup时,需要传入一个ExecutorService,也就是绑定一个线程池,该线程池负责两个任务:处理IO事件和触发CompletionHandler回调接口。代码如下:

      

    AsynchronousServerSocketChannel serverSocketChannel = null;
            try {
                ExecutorService executorService = Executors.newFixedThreadPool(80);
                AsynchronousChannelGroup channelGroup = AsynchronousChannelGroup.withThreadPool(executorService);
                serverSocketChannel = AsynchronousServerSocketChannel.open(channelGroup).bind(new InetSocketAddress(9000));
            }catch (IOException ioe){
                ioe.printStackTrace();
            }

        AsynchronousServerSocketChannel创建成功后,类似于ServerSocket,也是调用accept()方法来接受来自客户端的连接,由于异步IO实际的IO操作是交给操作系统来做的,用户进程只负责通知操作系统进行IO和接受操作系统IO完成的通知。所以异步的ServerChannel调用accept()方法后,当前线程不会阻塞,程序也不知道accept()方法什么时候能够接收到客户端请求并且操作系统完成网络IO,为解决这个问题,AIO为accept方法提供两个版本:

        Future<AsynchronousSocketChannel> accept() :开始接收客户端请求,如果当前线程需要进行网络IO(即获得AsynchronousSocketChannel),则应该调用该方法返回的Future对象的get()方法,但是get方法会阻塞该线程,所以这种方式是阻塞式的异步IO。

        <A> void accept(A attachment ,CompletionHandler<AsynchronousSocketChannel,? super A> handler):开始接受来自客户端请求,连接成功或失败都会触发CompletionHandler对象的相应方法。其中AsynchronousSocketChannel就代表该CompletionHandler处理器在处理连接成功时的result是AsynchronousSocketChannel的实例。

        而CompletionHandler接口中定义了两个方法,

          completed(V result , A attachment):当IO完成时触发该方法,该方法的第一个参数代表IO操作返回的对象,第二个参数代表发起IO操作时传入的附加参数。

          faild(Throwable exc, A attachment):当IO失败时触发该方法,第一个参数代表IO操作失败引发的异常或错误。

        使用第一种accept方法需要如下代码

        

    while (true){
                Future<AsynchronousSocketChannel> future = serverSocketChannel.accept();
                AsynchronousSocketChannel socketChannel = null;
                try {
                    socketChannel = future.get();
                    socketChannel.write(ByteBuffer.wrap("ssss".getBytes("UTF-8")));
                }catch (Exception e){
                    e.printStackTrace();
                }
    
    
            }

        通常使用第二种accept,实现自己的CompletionHandler实现类。

        而AsynchronousSocketChannel的的用法与Socket类似,由三个方法,但是不同的是每个方法又分为Future版本与CompletionHandler版本。

          connect():用于连接到指定端口,指定IP地址的服务器

          read()、write():完成读写。

        注意!使用异步Channel时,accept()、connect()、read()、write()等方法都不会阻塞,也就是说如果使用返回Future的这些方法,程序并不能直到什么时候成功IO,必须要使用get方法,等get方法的阻塞结束后才能确保IO完成,继续执行下面的操作。

  • 相关阅读:
    操作系统典型调度算法
    C++ volatile 关键字
    vue class绑定 组件
    yarn 基本用法
    vscode 插件安装以及首选项配置
    git 多人协作
    git Feature分支
    git Bug分支
    git 分支策略
    git 解决冲突
  • 原文地址:https://www.cnblogs.com/Theshy/p/7696313.html
Copyright © 2011-2022 走看看