소 백도 배 울 수 있 는 자바 NIO 의 Write 이벤트 입 니 다.

5880 단어 JavaNIO이벤트
NIO 서버
1.1 다 중 재 활용 개발 일반 절차

//     
Selector selector = Selector.open();
//    
ServerSocketChannel socketChannel = ServerSocketChannel.open();
//       
socketChannel.configureBlocking(false);
//    
socketChannel.bind(new InetSocketAddress(8080));
//    ,OP_ACCEPT    ServerSocketChannel 
socketChannel.register(selector, SelectionKey.OP_ACCEPT);
while (true) {
    selector.select();
    Set<SelectionKey> selectionKeys = selector.selectedKeys();
    Iterator<SelectionKey> iter = selectionKeys.iterator();
    while(iter.hasNext()) {
        SelectionKey key = iter.next();
        if(key.isAcceptable()) {
            SocketChannel channel = ((ServerSocketChannel)key.channel()).accept();
            channel.configureBlocking(false);
            channel.register(selector,SelectionKey.OP_READ);
        }
        
        if(key.isWritable()) {
        }
        
        if(key.isReadable()) {
            SocketChannel channel = (SocketChannel) key.channel();
            ByteBuffer readBuffer = ByteBuffer.allocate(1024);
            channel.read(readBuffer);
            readBuffer.flip();
            // handler Buffer
            //            
            //    write       ,    write  ?
            // channel.write(...)
        }
        iter.remove();
    }
}
1.2 해 혹 된 사건
NIO 쓰기 동작:
  • 이 벤트 를 왜 등 록 했 는 지
  • 언제 이벤트 등록
  • 왜 쓰 고 등록 취소 이벤트
  • 채널 이 selector 에 등록 되 어 있 으 면SelectionKey.OP_WRITEselector.select()를 호출 합 니 다.시스템 은 커 널 쓰기 버퍼 가 쓸 수 있 는 지 확인 합 니 다.
  • 쓸 수 있 으 면selector.select();즉시 돌아 와key.isWritable()
  • 언제 쓰 면 안 돼 요?예 를 들 어 버퍼 가 가득 찼 고 channel 은 shutdown OutPut 등 을 호출 했 습 니 다
  • 물론 등록 이벤트 외 에 채널 에서 write(...)를 직접 호출 할 수도 있 고 데 이 터 를 보 낼 수도 있 지만 유연성 이 부족 하고 CPU 를 낭비 할 수도 있 습 니 다.
    예 를 들 어 서버 에서 200 M 버 퍼 를 보 내 OP 를 사용 하 는 지 확인 해 야 합 니 다.WRITE 사건 의 차이.
    이벤트 사용 안 함
    프로그램 이 실 행 될 때 까지 200 M 파일 이 발 송 된 후에 야 계속 실 행 됩 니 다.비동기 이벤트 모델 의 사상 에 부합 되 지 않 습 니 다.버퍼 가 계속 쓸 수 없 는 상태 라면 이 과정 은 여기에서 순환 되 어 CPU 를 낭비 합 니 다.
    
    // 200M Buffer
    ByteBuffer buffer = .... 
    
    while(buffer.hasRemaining()) {
        //          socket's output buffer          
        //          ,   0  
        channel.write(buffer);
    }
    
    사용 이벤트
    
    if(key.isReadable()) {
    	// 200M Buffer
        ByteBuffer buffer = .... 
        //      
        key.interestOps(key.interestOps() | SelectionKey.OP_WRITE);
        //   Buffer
        key.attach(buffer);
    }
    //     
    if(key.isWritable()) {
        ByteBuffer buffer = (ByteBuffer) key.attachment();
        SocketChannel channel = (SocketChannel) key.channel();
        if (buffer.hasRemaining()) {
            channel.write(buffer)
        } else {
            //           ,             (       ,    )
            key.interestOps(key.interestOps() & ~SelectionKey.OP_WRITE);
        }
    }
    
    쓰기 이 벤트 를 실행 하려 면 먼저 selector 에 이 채널 의 쓰기 이 벤트 를 등록 해 야 합 니 다.등록 읽 기 이벤트 와 마찬가지 로 바 텀 쓰기 버퍼 에 시간 이 있 으 면 쓰기 이 벤트 를 촉발 합 니 다.일반적으로 바 텀 쓰기 버퍼 는 대부분 비어 있 습 니 다.그래서 보통 쓰기 이 벤트 를 등록 하면 바로 터치 합 니 다.cpu 가 공전 하지 않도록 쓰기 작업 이 끝 난 후에 쓰기 이 벤트 를 취소 하고 다음 에 쓰기 작업 이 있 을 때 다시 쓰기 이 벤트 를 등록 해 야 합 니 다.
    4.NIO 클 라 이언 트 엔 드
    개발 의 일반적 절차
    
    //      
    Selector selector = Selector.open();
    //     
    SocketChannel socketChannel = SocketChannel.open();
    //        
    socketChannel.configureBlocking(false);
    //   Server
    socketChannel.connect(new InetSocketAddress("127.0.0.1",8080));
    //     
    socketChannel.register(selector, SelectionKey.OP_CONNECT | SelectionKey.OP_READ);
    //     
    while (true) {
        selector.select();
        Set<SelectionKey> keys = selector.selectedKeys();
        Iterator<SelectionKey> iter = keys.iterator();
        while(iter.hasNext()) {
            SelectionKey key = iter.next();
            if(key.isConnectable()) {
                //              
                SocketChannel channel = (SocketChannel) key.channel();
                //       
                if(channel.finishConnect()) {
                    
                }
            }
            
            if(key.isReadable()) {
                SocketChannel channel = (SocketChannel) key.channel();
                ByteBuffer buffer = ByteBuffer.allocate(500 * 1024 * 1024);
                buffer.clear();
                channel.read(buffer);
                // buffer Handler
            }
            iter.remove();
        }
    }
    
    처음 OPCONNECT 사건 그리고 finish Connect 이해 못 해,OPCONNECT 이벤트 가 언제 시 작 됩 니까?특히 key.isConnectable()분기 에서 finish Connect 방법 을 호출 해 야 읽 기와 쓰기 작업 을 할 수 있 습 니 다.
    우선,non-blocking 모드 에서 socketChannel.connect(new InetSocketAddress("127.0.0.1",8080)를 호출 합 니 다.원 격 호스트 를 연결 합 니 다.연결 이 즉시 로 컬 연결 처럼 이 방법 은 즉시 true 로 돌아 갑 니 다.그렇지 않 으 면 이 방법 은 즉시 false 로 돌아 간 다음 시스템 밑 에서 세 번 악 수 를 하여 연결 을 만 듭 니 다.연결 은 두 가지 결과 가 있 습 니 다.하 나 는 성공 적 인 연결 입 니 다.두 번 째 는 이상 입 니 다.그러나 connect 방법 은 되 돌 아 왔 습 니 다.이 방법의 반환 값 이나 이상 을 통 해 사용자 프로그램 에 연결 하 는 상황 을 알 릴 수 없 기 때문에 OPCONNECT 이벤트 와 finish Connect 방법 으로 사용자 프로그램 에 알 립 니 다.시스템 밑 에 세 번 의 연결 이 성공 하 든 안 하 든 selector 는 깨 어 나 서 OP 를 촉발 합 니 다.CONNECT 이벤트,악수 에 성공 하고 이 연결 이 다른 스 레 드 에 의 해 닫 히 지 않 으 면 finishConnect 는 true 로 돌아 가 channle 읽 기와 쓰 기 를 순조롭게 진행 할 수 있 습 니 다.네트워크 가 고장 나 거나 원 격 호스트 가 고장 나 악수 가 성공 하지 못 하면 사용자 프로그램 은 finish Connect 방법 을 통 해 바 텀 의 이상 통 지 를 받 아 이상 을 처리 할 수 있 습 니 다.
    소 백도 배 울 수 있 는 자바 NIO 의 Write 이벤트 에 관 한 이 글 은 여기까지 소개 되 었 습 니 다.더 많은 자바 NIO 의 Write 이벤트 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 찾 아 보 세 요.앞으로 많은 응원 부 탁 드 리 겠 습 니 다!

    좋은 웹페이지 즐겨찾기