자바 NIO 원리 그림 분석 및 코드 구현

12662 단어 자바nio
등급: http://weixiaolu.iteye.com/blog/1479656
 
최근 hadop 의 RPC (Remote Procedure Call Protocol, 원 격 프로 세 스 호출 프로 토 콜) 를 분석 하고 있 습 니 다. 네트워크 를 통 해 원 격 컴퓨터 프로그램 에서 서 비 스 를 요청 하고 바 텀 네트워크 기술 을 알 필요 가 없 는 프로 토 콜 입 니 다. 참고 할 수 있 습 니 다. http://baike.baidu.com/view/32726.htm )메커니즘 을 발견 할 때 hadop 의 RPC 메커니즘 의 실현 은 주로 두 가지 기술 을 사용 했다. 동적 에이전트 (동적 에이 전 트 는 블 로 그 를 참고 할 수 있다. http://weixiaolu.iteye.com/blog/1477774 )자바 NIO 와. hadop 의 RPC 소스 코드 를 정확하게 분석 하기 위해 서 는 자바 NIO 의 원리 와 구체 적 인 실현 을 먼저 연구 할 필요 가 있다 고 생각 합 니 다. 이 블 로 그 는 주로 두 가지 방향 으로 자바 NIO 디 렉 터 리 를 분석 합 니 다. 1. 자바 NIO 와 I / O 의 차 이 를 차단 합 니 다.     1. 차단 I / O 통신 모델     2. 자바 NIO 원리 및 통신 모델 2. 자바 NIO 서버 와 클 라 이언 트 코드 구현 구체 적 인 분석: 1. 자바 NIO 와 차단 I / O 의 차이 1. 차단 I / O 통신 모델 만약 지금 차단 I / O 에 대해 어느 정도 알 고 있다 면, 차단 I / O 는 InputStream. read () 방법 을 호출 할 때 차단 되 어 있다 는 것 을 알 고 있 습 니 다. 데이터 가 올 때 (또는 시간 초과) 까지 기 다 려 야 돌아 올 것 입 니 다. 마찬가지 로, ServerSocket. accept () 를 호출 하고 있 습 니 다.방법 은 클 라 이언 트 연결 이 있어 야 돌아 올 때 까지 차단 합 니 다. 모든 클 라 이언 트 가 연결 되면 서버 에서 클 라 이언 트 의 요청 을 처리 하기 위해 스 레 드 를 시작 합 니 다. I / O 를 막 는 통신 모델 설명도 는 다음 과 같 습 니 다.
Java NIO原理图文分析及代码实现_第1张图片
자세히 분석 해 보면 차단 I / O 에 단점 이 있 을 것 입 니 다. 차단 I / O 통신 모델 에 따라 두 가지 단점 을 정리 하 였 습 니 다. 1. 클 라 이언 트 가 많 을 때 대량의 처리 스 레 드 를 만 들 것 입 니 다. 또한 모든 스 레 드 는 스 택 공간 과 CPU 시간 을 차지 해 야 합 니 다. 2. 차단 은 빈번 한 컨 텍스트 전환 을 가 져 올 수 있 고 대부분의 컨 텍스트 전환 은 무의미 할 수 있 습 니 다. 여기 서어떤 상황 에서 비 차단 식 I / O 는 응용 전망 이 있다. 자바 NIO 원리 및 통신 모델 자바 NIO 는 jdk 1.4 에서 사용 되 기 시 작 했 습 니 다. '새로운 I / O' 라 고도 할 수 있 고 비 차단 식 I / O 라 고도 할 수 있 습 니 다. 다음은 자바 NIO 의 작업 원리 입 니 다. 1. 하나의 전문 적 인 스 레 드 로 모든 IO 사건 을 처리 하고 배 포 를 책임 집 니 다. 2. 사건 구동 메커니즘: 사건 이 도 착 했 을 때 발생 하 는 것 이지 동시에 사건 을 감시 하 는 것 이 아니다. 3. 스 레 드 통신: 스 레 드 간 에 wait, notify 등 방식 으로 통신 합 니 다. 매번 컨 텍스트 전환 이 의미 가 있 습 니 다. 불필요 한 스 레 드 전환 을 줄 입 니 다. 몇 가지 자 료 를 읽 은 후에 제 가 이해 하 는 자바 NIO 의 작업 원리 도 를 붙 입 니 다.
Java NIO原理图文分析及代码实现_第2张图片
(비고: 모든 스 레 드 의 처리 절 차 는 데이터 읽 기, 디 코딩, 계산 처리, 인 코딩, 응답 보 내기 입 니 다.) 자바 NIO 서버 는 하나의 전문 스 레 드 만 시작 하여 모든 IO 사건 을 처리 합 니 다. 이런 통신 모델 은 어떻게 실현 되 었 습 니까? 하하, 우리 함께 그것 의 비밀 을 탐구 합 시다. 자바 NIO 는 양 방향 채널 (channel) 을 사용 합 니 다.단 방향 스 트림 (stream) 이 아 닌 데이터 전송 을 진행 합 니 다. 채널 에 관심 있 는 이 벤트 를 등록 할 수 있 습 니 다. 모두 다음 과 같은 네 가지 이벤트 가 있 습 니 다.
 
이벤트 이름
대응 값
서버 수신 클 라 이언 트 연결 이벤트
SelectionKey.OP_ACCEPT(16)
클 라 이언 트 연결 서버 이벤트
SelectionKey.OP_CONNECT(8)
읽 기 이벤트
SelectionKey.OP_READ(1)
이벤트 쓰기
SelectionKey.OP_WRITE(4)
 
 
 
 
 
 
 
 
 
 
 
서버 와 클 라 이언 트 는 각각 관리 채널 의 대상 을 유지 합 니 다. 우 리 는 selector 라 고 부 릅 니 다. 이 대상 은 하나 이상 의 채널 (channel) 의 이 벤트 를 감지 할 수 있 습 니 다. 서버 의 예 를 들 어 서버 의 selector 에 읽 기 이 벤트 를 등록 하면 클 라 이언 트 가 서버 에 데 이 터 를 보 내 고 I / O 를 막 을 때 read () 를 호출 합 니 다.방법 은 데 이 터 를 차단 적 으로 읽 고 NIO 서버 는 selector 에 읽 기 이 벤트 를 추가 합 니 다. 서버 의 처리 스 레 드 는 selector 에 문의 적 으로 접근 합 니 다. selector 에 방문 할 때 관심 있 는 이벤트 가 도착 하면 이 사건 들 을 처리 합 니 다. 관심 있 는 이벤트 가 도착 하지 않 으 면 관심 있 는 이벤트 가 도착 할 때 까지 스 레 드 를 처리 합 니 다. 다음은 제 이치 입 니 다.자바 NIO 의 통신 모델 설명도:
 
Java NIO原理图文分析及代码实现_第3张图片
 
2. 자바 NIO 서버 와 클 라 이언 트 코드 구현 자바 NIO 를 잘 이해 하기 위해 서버 와 클 라 이언 트 의 간단 한 코드 를 붙 여 구현 합 니 다. 서버:
package cn.nio;  
  
import java.io.IOException;  
import java.net.InetSocketAddress;  
import java.nio.ByteBuffer;  
import java.nio.channels.SelectionKey;  
import java.nio.channels.Selector;  
import java.nio.channels.ServerSocketChannel;  
import java.nio.channels.SocketChannel;  
import java.util.Iterator;  
  
/** 
 * NIO    
 * @author    
 */  
public class NIOServer {  
    //       
    private Selector selector;  
  
    /** 
     *     ServerSocket  ,               
     * @param port         
     * @throws IOException 
     */  
    public void initServer(int port) throws IOException {  
        //     ServerSocket    
        ServerSocketChannel serverChannel = ServerSocketChannel.open();  
        //           
        serverChannel.configureBlocking(false);  
        //        ServerSocket   port    
        serverChannel.socket().bind(new InetSocketAddress(port));  
        //            
        this.selector = Selector.open();  
        //            ,       SelectionKey.OP_ACCEPT  ,      ,  
        //       ,selector.select()   ,        selector.select()     。  
        serverChannel.register(selector, SelectionKey.OP_ACCEPT);  
    }  
  
    /** 
     *          selector           ,   ,      
     * @throws IOException 
     */  
    @SuppressWarnings("unchecked")  
    public void listen() throws IOException {  
        System.out.println("       !");  
        //     selector  
        while (true) {  
            //         ,    ;  ,          
            selector.select();  
            //   selector         ,            
            Iterator ite = this.selector.selectedKeys().iterator();  
            while (ite.hasNext()) {  
                SelectionKey key = (SelectionKey) ite.next();  
                //      key,        
                ite.remove();  
                //            
                if (key.isAcceptable()) {  
                    ServerSocketChannel server = (ServerSocketChannel) key  
                            .channel();  
                    //              
                    SocketChannel channel = server.accept();  
                    //         
                    channel.configureBlocking(false);  
  
                    //                
                    channel.write(ByteBuffer.wrap(new String("           ").getBytes()));  
                    //           ,             ,           。  
                    channel.register(this.selector, SelectionKey.OP_READ);  
                      
                    //           
                } else if (key.isReadable()) {  
                        read(key);  
                }  
  
            }  
  
        }  
    }  
    /** 
     *                  
     * @param key 
     * @throws IOException  
     */  
    public void read(SelectionKey key) throws IOException{  
        //         :       Socket    
        SocketChannel channel = (SocketChannel) key.channel();  
        //           
        ByteBuffer buffer = ByteBuffer.allocate(10);  
        channel.read(buffer);  
        byte[] data = buffer.array();  
        String msg = new String(data).trim();  
        System.out.println("       :"+msg);  
        ByteBuffer outBuffer = ByteBuffer.wrap(msg.getBytes());  
        channel.write(outBuffer);//            
    }  
      
    /** 
     *         
     * @throws IOException  
     */  
    public static void main(String[] args) throws IOException {  
        NIOServer server = new NIOServer();  
        server.initServer(8000);  
        server.listen();  
    }  
  
}  

 
클 라 이언 트:
package cn.nio;  
  
import java.io.IOException;  
import java.net.InetSocketAddress;  
import java.nio.ByteBuffer;  
import java.nio.channels.SelectionKey;  
import java.nio.channels.Selector;  
import java.nio.channels.SocketChannel;  
import java.util.Iterator;  
  
/** 
 * NIO    
 * @author    
 */  
public class NIOClient {  
    //       
    private Selector selector;  
  
    /** 
     *     Socket  ,               
     * @param ip        ip 
     * @param port                      
     * @throws IOException 
     */  
    public void initClient(String ip,int port) throws IOException {  
        //     Socket    
        SocketChannel channel = SocketChannel.open();  
        //           
        channel.configureBlocking(false);  
        //            
        this.selector = Selector.open();  
          
        //         ,             ,   listen()      
        // channel.finishConnect();        
        channel.connect(new InetSocketAddress(ip,port));  
        //            ,       SelectionKey.OP_CONNECT  。  
        channel.register(selector, SelectionKey.OP_CONNECT);  
    }  
  
    /** 
     *          selector           ,   ,      
     * @throws IOException 
     */  
    @SuppressWarnings("unchecked")  
    public void listen() throws IOException {  
        //     selector  
        while (true) {  
            selector.select();  
            //   selector           
            Iterator ite = this.selector.selectedKeys().iterator();  
            while (ite.hasNext()) {  
                SelectionKey key = (SelectionKey) ite.next();  
                //      key,        
                ite.remove();  
                //         
                if (key.isConnectable()) {  
                    SocketChannel channel = (SocketChannel) key  
                            .channel();  
                    //       ,       
                    if(channel.isConnectionPending()){  
                        channel.finishConnect();  
                          
                    }  
                    //         
                    channel.configureBlocking(false);  
  
                    //                
                    channel.write(ByteBuffer.wrap(new String("           ").getBytes()));  
                    //           ,             ,           。  
                    channel.register(this.selector, SelectionKey.OP_READ);  
                      
                    //           
                } else if (key.isReadable()) {  
                        read(key);  
                }  
  
            }  
  
        }  
    }  
    /** 
     *                  
     * @param key 
     * @throws IOException  
     */  
    public void read(SelectionKey key) throws IOException{  
        //     read      
    }  
      
      
    /** 
     *         
     * @throws IOException  
     */  
    public static void main(String[] args) throws IOException {  
        NIOClient client = new NIOClient();  
        client.initClient("localhost",8000);  
        client.listen();  
    }  
  
}  

 
소결: 드디어 동적 에이전트 와 자바 NIO 를 분 석 했 습 니 다. 하하, 다음은 hadop 의 RPC 체제 소스 코드 를 분석 하 겠 습 니 다. 블 로그 주소: http://weixiaolu.iteye.com/blog/1504898 。그러나 자바 NIO 의 이해 에 이의 가 있다 면 함께 토론 하 시 는 것 을 환영 합 니 다.

좋은 웹페이지 즐겨찾기