美文网首页
Java NIO(7) - 非阻塞式网络通信应用

Java NIO(7) - 非阻塞式网络通信应用

作者: 21号新秀_邓肯 | 来源:发表于2020-05-15 11:19 被阅读0次

    4.5 SocketChannel

    Java NIO中的SocketChannel是一个连接到TCP网络套接字的通道。

    操作步骤:

    • 打开 SocketChannel
    • 读写数据
    • 关闭 SocketChannel
      1. 客户端
        @Test
        public void client() {
            SocketChannel socketChannel = null;
            try {
                //1.获取通道
                socketChannel = 
                        SocketChannel.open(new InetSocketAddress(6666));
    
                //2.切换非阻塞模式
                socketChannel.configureBlocking(false);
    
                //3.分配指定大小的缓冲区
                ByteBuffer buf = ByteBuffer.allocate(1024);
    
                //4.发送数据给服务器
                Scanner scanner = new Scanner(System.in);
    
                while (scanner.hasNext()) {
                    String str = scanner.next();
                    buf.put((new Date().toString() + "\n" + str).getBytes());
                    buf.flip();
                    socketChannel.write(buf);
                    buf.clear();
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (socketChannel != null) {
                    try {
                        socketChannel.close();
                    } catch (IOException ie) {
                        ie.printStackTrace();
    
                    }
                }
            }
        }
     
    

    4.6 ServerSocketChannel

    Java NIO中的 ServerSocketChannel 是一个可以监听新进来的TCP连接的通道,就像标准IO中的ServerSocket一样

        @Test
        public void service() {
            ServerSocketChannel socketChannel = null;
            SocketChannel sc = null;
            try {
                //1.获取通道
                socketChannel = ServerSocketChannel.open();
    
                //2.切换非阻塞模式
                socketChannel.configureBlocking(false);
    
                //3.绑定连接
                socketChannel.bind(new InetSocketAddress(6666));
    
                //4. 获取选择器
                Selector selector = Selector.open();
    
                //5.将通道注册到选择器上, 并且指定"监听接受事件"
                socketChannel.register(selector, SelectionKey.OP_ACCEPT);
    
                //6.轮询式获取选择器上已经"准备就绪"的事件
                while (selector.select() > 0) {
    
                    //7.获取当前选择器中所有注册的"选择键(已就绪的监听事件)"
                    Iterator<SelectionKey> it = selector.selectedKeys().iterator();
    
                    while (it.hasNext()) {
                        //8. 获取准备"就绪"的是事件
                        SelectionKey sk = it.next();
    
                        //9. 判断具体是什么事件就绪
                        //接受事件是否就绪
                        if (sk.isAcceptable()) {
                            //10. 若"接受就绪", 获取客户端连接
                            sc = socketChannel.accept();
    
                            //11. 切换非阻塞模式
                            sc.configureBlocking(false);
    
                            //12. 将通道注册到选择器上
                            sc.register(selector, SelectionKey.OP_READ);
                        } else if (sk.isReadable()) {
                            //13. 获取当前选择器上"读就绪"状态的通道
                            sc = (SocketChannel) sk.channel();
    
                            //14.读取
                            ByteBuffer buf = ByteBuffer.allocate(1024);
    
                            int len = 0;
                            while ((len = sc.read(buf)) > 0) {
                                buf.flip();
                                System.out.println(new String(buf.array(), 0, len));
                                buf.clear();
                            }
                        }
                    }
                    it.remove();
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (socketChannel != null) {
                    try {
                        socketChannel.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    
    

    4.7 DatagramChannel

    Java NIO中的DatagramChannel是一个能收发UDP包的通道。
    操作步骤:

    • 打开 DatagramChannel
    • 接收/发送数据
        
        @Test
        public void send() throws IOException{
            DatagramChannel dc = DatagramChannel.open();
            
            dc.configureBlocking(false);
            
            ByteBuffer buf = ByteBuffer.allocate(1024);
            
            Scanner scan = new Scanner(System.in);
            
            while(scan.hasNext()){
                String str = scan.next();
                buf.put((new Date().toString() + ":\n" + str).getBytes());
                buf.flip();
                dc.send(buf, new InetSocketAddress("127.0.0.1", 9898));
                buf.clear();
            }
            
            dc.close();
        }
        
        @Test
        public void receive() throws IOException{
            DatagramChannel dc = DatagramChannel.open();
            
            dc.configureBlocking(false);
            
            dc.bind(new InetSocketAddress(9898));
            
            Selector selector = Selector.open();
            
            dc.register(selector, SelectionKey.OP_READ);
            
            while(selector.select() > 0){
                Iterator<SelectionKey> it = selector.selectedKeys().iterator();
                
                while(it.hasNext()){
                    SelectionKey sk = it.next();
                    
                    if(sk.isReadable()){
                        ByteBuffer buf = ByteBuffer.allocate(1024);
                        
                        dc.receive(buf);
                        buf.flip();
                        System.out.println(new String(buf.array(), 0, buf.limit()));
                        buf.clear();
                    }
                }
                
                it.remove();
            }
        }
    

    相关文章

      网友评论

          本文标题:Java NIO(7) - 非阻塞式网络通信应用

          本文链接:https://www.haomeiwen.com/subject/rcmqohtx.html