【Java】Java AIO 사용

공중 번호 에 관심 을 가 져 주 십시오:
nullobject 。
글 은 개인 블 로그 에 처음 게재 되 었 다.
https://www.nullobject.cn,공중 번호
nullobject 동기 화 업데이트.
이 글 은 주로 자바 AIO 네트워크 프로 그래 밍 을 소개 한다.
1.아이 오 는 무엇 인가
본 고 에서 말 한 AIO 는 특히Java환경 에서 의 AIO 를 가리킨다.AIO 는java중 IO 모델 의 일종 으로 NIO 의 개 선·강화 로 JDK 1.7 버 전 업데이트 에 따라 JDK 의 니 오 백 에 통합 되 기 때문에 AIO 는 NIO 2.0 이 라 고도 불 린 다.전통 적 인 BIO(Blocking IO,동기 식 블록 모델 과 달리 JDK 1.4 이전에 JDK 에 존 재 했 고 NIO 는 JDK 1.4 버 전에 서 업 데 이 트 를 발표 했다)의 블록 식 읽 기와 쓰 기 를 제 공 했 으 며 AIO 는 연결 구축 부터 읽 기,쓰기 까지 전 비동기 동작 을 제공 했다.AIO 는 비동기 적 인 파일 읽 기와 쓰기,네트워크 통신 에 사용 할 수 있다.본 고 는 AIO 를 어떻게 사용 하여 간단 한 네트워크 통신 과 AIO 의 비교적 관건 적 인 API 를 실현 하 는 지 소개 할 것 이다.
2.간단 한 사용
먼저 서버 단 을 예 로 들 면AsynchronousServerSocketChannel예 시 를 만 들 고 감청 포트 를 연결 한 다음 에 감청 클 라 이언 트 연결 을 시작 해 야 합 니 다.
public class SimpleAIOServer {

    public static void main(String[] args) {
        try {
            final int port = 5555;
            //      ServerSocket     AsynchronousServerSocketChannel  :
            AsynchronousServerSocketChannel serverSocketChannel = AsynchronousServerSocketChannel.open();
            //          serverSocketChannel:  
            serverSocketChannel.bind(new InetSocketAddress(port));
            //    CompletionHandler    handler,
            //     handler                  、    ,      。
            CompletionHandler handler = new CompletionHandler() {
                @Override
                public void completed(final AsynchronousSocketChannel result, final Object attachment) {
                    //              
                    serverSocketChannel.accept(attachment, this);
                    try {
                        System.out.println("       :" + result.getRemoteAddress()
                                                              .toString());
                        //                
                        result.write(ByteBuffer.wrap("From Server:Hello i am server".getBytes()))
                              .get();
                        ByteBuffer readBuffer = ByteBuffer.allocate(128);
                        //            
                        result.read(readBuffer)
                              .get();
                        System.out.println(new String(readBuffer.array()));

                    } catch (IOException | InterruptedException | ExecutionException e) {
                        e.printStackTrace();
                    }
                }

                @Override
                public void failed(final Throwable exc, final Object attachment) {
                    System.out.println("   :" + exc.getMessage());
                }
            };
            serverSocketChannel.accept(null, handler);
            //   serverSocketChannel.accept(null, handler);       ,       ,
            //                        ,
            //               (             )             。
            TimeUnit.MINUTES.sleep(Integer.MAX_VALUE);
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }
}

그 중에서result은 현재 받 아들 이 는 클 라 이언 트 의 연결 세 션 을 나타 내 고 클 라 이언 트 와 의 통신 은 모두 이 연결 세 션 을 통 해 이 루어 져 야 한 다 는 것 을 나타 낸다.
클 라 이언 트 쪽:
public class SimpleAIOClient {

    public static void main(String[] args) {
        try {
            //     SocketChannel     AsynchronousSocketChannel  
            AsynchronousSocketChannel client = AsynchronousSocketChannel.open();
            //              
            client.connect(new InetSocketAddress("127.0.0.1", 5555), null, new CompletionHandler() {
                @Override
                public void completed(final Void result, final Void attachment) {
                    System.out.println("        !");
                    try {
                        //                
                        client.write(ByteBuffer.wrap("From client:Hello i am client".getBytes()))
                              .get();
                        ByteBuffer readBuffer = ByteBuffer.allocate(128);
                        //            
                        client.read(readBuffer)
                              .get();
                        System.out.println(new String(readBuffer.array()));
                    } catch (InterruptedException | ExecutionException e) {
                        e.printStackTrace();
                    }
                }

                @Override
                public void failed(final Throwable exc, final Void attachment) {
                    exc.printStackTrace();
                }
            });
            TimeUnit.MINUTES.sleep(Integer.MAX_VALUE);
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }
}

3.AIO 주요 API 상세 설명
2절 예 를 통 해 알 수 있 듯 이 가장 간단 한 AIO socket 통신 server,client 를 실현 하려 면 주로 이러한 관련 클래스 와 인터페이스 가 필요 합 니 다.
  • AsynchronousServerSocketChannel서버 소켓 채널 류 는 서버 소켓 의 생 성과 감청 을 책임 집 니 다.
  • AsynchronousSocketChannel클 라 이언 트 Socket 채널 류 는 클 라 이언 트 메시지 읽 기와 쓰 기 를 책임 집 니 다.
  • CompletionHandler메시지 처리 리 턴 인터페이스 로 비동기 IO 작업 결 과 를 소비 하 는 메시지 처리 장치 입 니 다.
  • ByteBuffer통신 과정 에서 읽 고 써 야 할 소식 을 담 는 다.

  • 이 밖 에 비동기 채널 자원 공유 에 사용 할AsynchronousChannelGroup류 도 선택 할 수 있 으 며,다음은 이러한 주요 인터페이스 와 사용 을 일일이 소개 할 것 이다.
    3.1.1 AsynchronousServerSocketChannel
    Asynchronous Server SocketChannel 은 하나 입 니 다.
    스 트림 감청 소켓 의 비동기 채널.AsynchronousServerSocketChannel의 사용 은 세 가지 절 차 를 거 쳐 야 합 니 다.채널 생 성/열기,바 인 딩 주소 와 포트 와 감청 클 라 이언 트 연결 요청 을 거 쳐 야 합 니 다.
    1.채널 생 성/열기:간단하게AsynchronousServerSocketChannel의 정적 방법open()을 호출 하여AsynchronousServerSocketChannel인 스 턴 스 를 만 들 수 있 습 니 다.
    try {
      AsynchronousServerSocketChannel serverSocketChannel = AsynchronousServerSocketChannel.open();
    } catch (IOException e) {
      e.printStackTrace();
    }

    채널 을 여 는 데 실 패 했 을 때 이상IOException을 던 집 니 다.AsynchronousServerSocketChannel는 그룹 내 채널 자원 공 유 를 실현 하기 위해 채널 그룹AsynchronousChannelGroup을 설정 하 는 기능 을 제공 했다.지정 한 그룹 채널 을 만 들 기 위해 서open(AsynchronousChannelGroup)리 셋 방법 을 호출 할 수 있 습 니 다:
    try {
      ExecutorService pool = Executors.newCachedThreadPool();
      AsynchronousChannelGroup group = AsynchronousChannelGroup.withCachedThreadPool(pool, 10);
      AsynchronousServerSocketChannel serverSocketChannel = AsynchronousServerSocketChannel.open(group);
    } catch (IOException e) {
      e.printStackTrace();
    }
    AsynchronousChannelGroup그룹 에 연 결 된 비동기 채널 에서 발생 하 는 I/O 작업 을 처리 하 는 데 필요 한 메커니즘 을 봉 했다.각각AsynchronousChannelGroup은 I/O 이 벤트 를 처리 하고 그룹 내 채널 에서 실 행 된 비동기 작업 결 과 를 전달 하 는 데 사용 되 는 completion-handlers 스 레 드 탱크 와 연결 되 어 있 습 니 다.I/O 이 벤트 를 처리 하 는 것 외 에 이 스 레 드 탱크 는 비동기 I/O 작업 을 지원 하 는 다른 작업 을 처리 할 수 있 습 니 다.위의 예 에서 볼 수 있 듯 이 지정AsynchronousChannelGroup방식 으로AsynchronousServerSocketChannel을 열 면 server channel 이 실행 하 는 스 레 드 풀 을 맞 출 수 있 습 니 다.AsynchronousChannelGroup에 대한 상세 한 소 개 는 공식 문서 의 주석 을 볼 수 있다.지정 하지 않 으 면AsynchronousChannelGroup기본 그룹 으로 분 류 됩 니 다.
    2.바 인 딩 주소 와 포트:호출AsynchronousServerSocketChannel방법 으로 감청 주소 와 포트 를 연결 합 니 다.
    //     InetSocketAddress             ,      ip,   InetSocketAddress(ip,port)        
    serverSocketChannel.bind(new InetSocketAddress(port));

    3.클 라 이언 트 연결 요청 을 감청 하고 받 습 니 다.
    클 라 이언 트 연결 요청 을 감청 하 는 것 은 주로 호출AsynchronousServerSocketChannel.bind(SocketAddress)방법 으로 이 루어 집 니 다.AsynchronousServerSocketChannel.accept()두 가지 무 거 운 적재 방법 이 있다.
    public abstract void accept(A,CompletionHandler);
    public abstract Future accept();

    이 두 가지 리 셋 방법의 행위 방식 은 완전히 같다.사실상 AIO 의 많은 비동기 API 는 이러한 리 셋 방법 을 봉인 했다.accept()리 셋 파 라미 터 를 제공 하거나CompletionHandle유형 변 수 를 되 돌려 준다.Future인 터 페 이 스 를 사용 한 사람 은 모두 알 고 있 으 며,호출Feture방법 으로 호출 결 과 를 막 을 수 있다.첫 번 째 리 셋 방법 으로 예 를 들 어 새로운 클 라 이언 트 연결 을 받 거나 accept 작업 에 이상 이 발생 하면 CompletionHandler 를 통 해 결 과 를 사용자 에 게 되 돌려 줍 니 다.
    serverSocketChannel
    .accept(serverSocketChannel, new CompletionHandler() {
              @Override
              public void completed(final AsynchronousSocketChannel result,
                                    final AsynchronousServerSocketChannel attachment) {
                //              
                // result           
                //       result        
              }
    
              @Override
              public void failed(final Throwable exc, final AsynchronousServerSocketChannel attachment) {
                // accept     
              }
            });

    주의해 야 할 것 은Feture.get()스 레 드 가 안전 하지만 같은 시간 에 하나의 accept 작업 만 허용 할 수 있 습 니 다.따라서 이전AsynchronousServerSocketChannel작업 이 끝 난 후에 야 다음accept을 시작 할 수 있 습 니 다.
    serverSocketChannel
    .accept(serverSocketChannel, new CompletionHandler() {
              @Override
              public void completed(final AsynchronousSocketChannel result,
                                    final AsynchronousServerSocketChannel attachment) {
                //           ,    accept    
                //               
                serverSocketChannel.accept(serverSocketChannel,this);
                // result           
                //       result        
              }
              ...
            });

    또한 다음 과 같은 방법 으로acceptAsynchronousServerSocketChannel옵션 을 얻 고 설정 할 수 있 습 니 다.
    //   socket  
    serverSocketChannel.setOption(StandardSocketOptions.SO_KEEPALIVE,true);
    //   socket    
    boolean keepAlive = serverSocketChannel.getOption(StandardSocketOptions.SO_KEEPALIVE);
    

    이 중socket클래스 는 자주 사용 하 는 socket 설정 옵션 을 패키지 합 니 다.
    로 컬 주소 가 져 오기:
    InetSocketAddress address = (InetSocketAddress) serverSocketChannel.getLocalAddress();
    

    3.1.2 AsynchronousSocketChannel
    Asynchronous SocketChannel 은 하나 입 니 다.
    스 트림 연결 소켓 의 비동기 채널.StandardSocketOptions서버 와 클 라 이언 트 간 의 연결 통 로 를 나타 낸다.클 라 이언 트 는 호출AsynchronousSocketChannel정적 방법AsynchronousSocketChannel을 통 해 만 들 수 있 고 서버 는 호출open()방법 을 통 해 AIO 내부 가 적당 할 때 만 들 수 있 습 니 다.다음은 클 라 이언 트 실현 을 예 로 들 어 소개AsynchronousServerSocketChannel.accept().
    1.Asynchronous SocketChannel 을 만 들 고 서버 에 연결 합 니 다.AsynchronousSocketChannel을 통 해open()인 스 턴 스 를 만 들 고 열 고AsynchronousSocketChannel방법 으로 서버 에 연결 해 야 서버 와 상호작용 할 수 있 습 니 다.
    //     socket  
    AsynchronousSocketChannel socketChannel = AsynchronousSocketChannel.open();
    //         
    socketChannel.connect(new InetSocketAddress(ip,port)).get();
    //     ,       read、write  
    

    같은connect(),AsynchronousServerSocketChannelAsynchronousSocketChannel방법 을 제공 하여 채널 그룹 과 맞 춤 형 스 레 드 풀 을 지정 하 는 데 사용 했다.open(AsynchronousChannelGroup)socketChannel.connect()리 셋 과CompletionHandler리 셋 두 가지 리 셋 방법 을 제공 했다.위의 예 는 Future 리 턴 값 을 가 진 리 셋 을 사용 하고Future방법 으로 연결 이 완 료 될 때 까지 막 았 다.
    2.메시지 발송:
    하나의get()대상 을 구축 하고 호출ByteBuffer방법 으로 비동기 로 메 시 지 를 보 내 고socketChannel.write(ByteBuffer)리 셋 을 통 해 결 과 를 보 낼 수 있 습 니 다.
    ByteBuffer writeBuf = ByteBuffer.wrap("From socketChannel:Hello i am socketChannel".getBytes());
    socketChannel.write(writeBuf, null, new CompletionHandler() {
      @Override
      public void completed(final Integer result, final Object attachment) {
        //     ,result:        
      }
    
      @Override
      public void failed(final Throwable exc, final Object attachment) {
        //     
      }
    });
    

    3.메시지 읽 기:
    지정 한 수신 길이CompletionHandler를 구축 하여 데 이 터 를 수신 하고 호출ByteBuffer방법 으로 메 시 지 를 읽 고socketChannel.read()처 리 를 통 해 결 과 를 읽 습 니 다.
    ByteBuffer readBuffer = ByteBuffer.allocate(128);
    socketChannel.read(readBuffer, null, new CompletionHandler() {
      @Override
      public void completed(final Integer result, final Object attachment) {
        //     ,result:        。            result=-1。
      }
    
      @Override
      public void failed(final Throwable exc, final Object attachment) {
        //     
      }
    });
    

    또한,CompletionHandlersocket 옵션 을 설정/가 져 오 는 방법 도 패키지 되 어 있 습 니 다.
    //   socket  
    socketChannel.setOption(StandardSocketOptions.SO_KEEPALIVE,true);
    //   socket    
    boolean keepAlive = socketChannel.getOption(StandardSocketOptions.SO_KEEPALIVE);
    

    3.1.3 CompletionHandler
    Complete Handler
    비동기 I/O 작업 결 과 를 소비 하 는 프로세서.
    AIO 에서 정의 하 는 비동기 채널 은 하나의AsynchronousSocketChannel프로세서 가 비동기 작업 의 결 과 를 소비 할 수 있 도록 합 니 다.앞에서 도 볼 수 있 듯 이 AIO 의 대부분 비동기 I/O 작업 인 터 페 이 스 는 하나의 띠CompletionHandler유형의 매개 변 수 를 재 부팅 하 는 방법 을 봉 하여CompletionHandlerAIO 의 비동기 I/O 작업 결 과 를 편리 하 게 처리 할 수 있다.CompletionHandler는 두 개의 범 형 매개 변 수 를 가 진 인터페이스 로 두 개의 인터페이스 방법 을 설명 했다.
    public interface CompletionHandler {
        void completed(V result, A attachment);
        void failed(Throwable exc, A attachment);
    }
    

    그 중에서 범 형 V 는 I/O 작업 의 결과 유형 을 나타 내 고 이 유형의 매개 변 수 를 통 해 I/O 작업 의 결 과 를 소비 합 니 다.범 형 A 는 I/O 작업 에 추 가 된 대상 유형 으로 이 유형의 매개 변 수 를 통 해 필요 한 변 수 를 CompletionHandler 구현 에 전송 하여 사용 할 수 있 습 니 다.따라서 AIO 의 대부분 비동기 I/O 작업 은 이러한 과부하 방법 이 있 습 니 다.
     void ioOperate(params,A attachment,CompletionHandler handler);
    

    예 를 들 어CompletionHandler방법:
    public abstract void accept(A attachment,CompletionHandler handler);
    AsynchronousServerSocketChannel.accept()방법 등:
    public final void write(ByteBuffer src,A attachment,CompletionHandler handler)

    I/O 작업 이 성공 적 으로 완료 되면AsynchronousSocketChannel.write()방법 으로 되 돌아 가 고completed방법 은 I/O 작업 이 실 패 했 을 때 되 돌아 갑 니 다.주의해 야 할 것 은failed의 실현 에 있어 서 작업 결 과 를 처리 하 더 라 도 호출 스 레 드 를 계속 차지 하지 않도록 다른CompletionHandler프로 세 서 를 나 누 어 주지 않도록 해 야 한 다 는 것 이다.
    4 The End :)

    좋은 웹페이지 즐겨찾기