NIOはTCPネットワーク通信を実現する


NIOはTCPネットワーク通信を実現する
従来のソケットはIOモードをブロックして実現したソケット通信を採用しているが,ここでのブロックは実際にはプログラムとカーネルが相互作用するときのモードであり,NIOではNIOの特性を利用して非ブロック形式のソケット通信を実現できる
1.実装手順
  • サービス側のポートリスニング
  • を実現
  • は、サービス側がクライアント接続を取得し、Selectorに登録する
  • を実現する.
  • メッセージ解析
  • を実装
  • クライアントコードを実装し、
  • をテストする.
    2.サービス側実現
    2.1サービス側のポートリスニングの実現
    public class MyServer {
         
    
        private ServerSocketChannel serverSocketChannel;
        private Selector selector;
    
        /**
         *      
         */
        public void start(Integer port) throws Exception{
         
            serverSocketChannel = ServerSocketChannel.open();
            selector = Selector.open();
            //      
            serverSocketChannel.socket().bind(new InetSocketAddress(port));
            //        
            serverSocketChannel.configureBlocking(false);
            //   Selector 
            serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
            startListener();
        }
        
        /**
         *              
         */
        private void startListener() throws Exception {
         
            while (true) {
         
                //         select          
                if (selector.select(1000) == 0) {
         
                    System.out.println("current not exists task");
                    continue;
                }
                //                 key
                Set<SelectionKey> selectionKeys = selector.selectedKeys();
                Iterator<SelectionKey> iterator = selectionKeys.iterator();
            }
        }
    }
    

    2.2接続処理の実現
  • は、取得したばかりのすべてのイベントのあるkeyを巡回し、イベントタイプがAcceptであるkeyを見つけるだけで、対応するチャネルをselectorに登録することができる
  • である.
    
        private void startListener() throws Exception {
         
            while (true) {
         
                if (selector.select(1000) == 0) {
         
                    System.out.println("current not exists task");
                    continue;
                }
                //                 key
                Set<SelectionKey> selectionKeys = selector.selectedKeys();
                Iterator<SelectionKey> iterator = selectionKeys.iterator();
    			
                //      key         Accept key
                while (iterator.hasNext()) {
         
                    SelectionKey key = iterator.next();
                    if (key.isAcceptable())
                        handleConnection();
                    iterator.remove();
                }
            }
        }
    
        /**
         *       
         */
        private void handleConnection() throws Exception {
         
            SocketChannel socketChannel = serverSocketChannel.accept();
            socketChannel.configureBlocking(false);
            socketChannel.register(selector, SelectionKey.OP_READ, ByteBuffer.allocate(1024));
        }
    
    

    2.4メッセージ処理
  • は、取得したばかりのすべてのイベントのあるkeyを巡回し、イベントタイプがReadableのkeyを見つけ、チャネル内のメッセージ
  • を取得する必要がある.
      private void startListener() throws Exception {
         
            while (true) {
         
                if (selector.select(1000) == 0) {
         
                    System.out.println("current not exists task");
                    continue;
                }
                Set<SelectionKey> selectionKeys = selector.selectedKeys();
                Iterator<SelectionKey> iterator = selectionKeys.iterator();
    
                while (iterator.hasNext()) {
         
                    SelectionKey key = iterator.next();
                    if (key.isAcceptable())
                        handleConnection();
                    if (key.isReadable())
                        handleMsg(key);
                    iterator.remove();
                }
            }
        }
    
        private void handleMsg(SelectionKey key) throws Exception {
         
            SocketChannel channel = (SocketChannel) key.channel();
            ByteBuffer attachment = (ByteBuffer) key.attachment();
            channel.read(attachment);
            System.out.println("current msg: " + new String(attachment.array()));
        }
    
    

    2.5サービス・エンドの完全なコード
    public class MyServer {
         
    
        private ServerSocketChannel serverSocketChannel;
        private Selector selector;
    
        public void start(Integer port) throws Exception{
         
            serverSocketChannel = ServerSocketChannel.open();
            selector = Selector.open();
            serverSocketChannel.socket().bind(new InetSocketAddress(port));
            serverSocketChannel.configureBlocking(false);
            serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
            startListener();
        }
    
        private void startListener() throws Exception {
         
            while (true) {
         
                if (selector.select(1000) == 0) {
         
                    System.out.println("current not exists task");
                    continue;
                }
                Set<SelectionKey> selectionKeys = selector.selectedKeys();
                Iterator<SelectionKey> iterator = selectionKeys.iterator();
    
                while (iterator.hasNext()) {
         
                    SelectionKey key = iterator.next();
                    if (key.isAcceptable())
                        handleConnection();
                    if (key.isReadable())
                        handleMsg(key);
                    iterator.remove();
                }
            }
        }
    
        private void handleMsg(SelectionKey key) throws Exception {
         
            SocketChannel channel = (SocketChannel) key.channel();
            ByteBuffer attachment = (ByteBuffer) key.attachment();
            channel.read(attachment);
            System.out.println("current msg: " + new String(attachment.array()));
        }
    
        private void handleConnection() throws Exception {
         
            SocketChannel socketChannel = serverSocketChannel.accept();
            socketChannel.configureBlocking(false);
            socketChannel.register(selector, SelectionKey.OP_READ, ByteBuffer.allocate(1024));
        }
    
    
        public static void main(String[] args) throws Exception {
         
            MyServer myServer = new MyServer();
            myServer.start(8888);
        }
    }
    
    

    3.クライアント実装
    public class MyClient {
         
        public static void main(String[] args) throws Exception {
         
            SocketChannel socketChannel = SocketChannel.open();
            socketChannel.configureBlocking(false);
    		
            //      
            if (!socketChannel.connect(new InetSocketAddress("127.0.0.1", 8888))) {
         
                while (!socketChannel.finishConnect()) {
         
                    System.out.println("connecting...");
                }
            }
    		//    
            String str = "hello netty";
            ByteBuffer byteBuffer = ByteBuffer.wrap(str.getBytes());
            socketChannel.write(byteBuffer);
            System.in.read();
        }
    }