java nio做即使通讯的使用

199 阅读7分钟

 在NIO中有几个核心对象需要掌握:缓冲区(Buffer)、通道(Channel)、选择器(Selector)。 

缓冲区Buffer 

缓冲区实际上是一个容器对象,更直接的说,其实就是一个数组,在NIO库中,所有数据都是用缓冲区处理的。在读取数据时,它是直接读到缓冲区中的; 在写入数据时,它也是写入到缓冲区中的;任何时候访问 NIO 中的数据,都是将它放到缓冲区中。而在面向流I/O系统中,所有数据都是直接写入或者直接将数据读取到Stream对象中。 

首先建立服务器端,代码如下 

<span style="font-size:14px;"> </span><span style="font-size:18px;">ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();                       serverSocketChannel.configureBlocking(false); 

                    ServerSocket serverSocket = serverSocketChannel.socket();                     serverSocket.bind(new InetSocketAddress(port)); 

                    selector = Selector.open(); 

                   serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);                                    System.out.println("server start on port:" + port); </span> 

先建立通道,然后得到一个ServerSocket并绑定到一个端口上,Selector selector,这个就是nio中的选择器, 

<span style="font-size:18px;">serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);</span> 

这句话的意思就是在我们的通道上注册选取器选择可接受的请求(SelectionKey.OP_ACCEPT) 我们还需要一个方法去轮询我们的请求 

<span style="font-size:18px;">while (true) {

                                    try { 

                                               int readyChannels = selector.select(); 

                                               if(readyChannels == 0) continue; 

                                               Set<SelectionKey> keys = selector.selectedKeys(); 

                                               for (SelectionKey key : keys) { 

                                                            if(key.isValid()) 

                                                               handle(key); 

                                                           keys.remove(key); 

                                               }; 

                                        } catch (Exception e) { 

                                                   e.printStackTrace(); 

                                                   break; 

                                       } 

</span><span style="font-size:14px;"> 

                             }</span> 

首先选择器去找到所有的请求,我们通过SelectionKey可以去处理这些请求 我们如何处理呢?? 

private void handle(SelectionKey selectionKey) throws Exception { 

                         ServerSocketChannel server = null; 

                         SocketChannel client = null; 

                         if (selectionKey.isAcceptable()) { 

                                     server = (ServerSocketChannel) selectionKey.channel(); 

                                     client = server.accept(); 

                                     client.configureBlocking(false); 

                                     client.register(selector, SelectionKey.OP_READ); 

                          } else if (selectionKey.isReadable()) { 

                                   client = (SocketChannel) selectionKey.channel(); 

                                   if (client.isConnected()) { 

                                              try { 

                                                         rBuffer.clear(); 

                                                         while (client.read(rBuffer) > 0) { 

                                                                     rBuffer.flip(); 

                                                        } 

                                                        byte[] save = rBuffer.array(); 

                                                 

                                                        ByteArrayInputStream bi = new ByteArrayInputStream(save); 

                                                        ObjectInputStream oi = new ObjectInputStream(bi); 


                                                        bi.close(); 

                                                        oi.close(); 

                                                       

                                                        if (client.isConnected()) { 

                                                                   client.register(selector, SelectionKey.OP_READ); 

                                                       } else { 

                                                                 System.out.println("2连接断开aaaaaa"); 

                                                       } 


                                            } catch (IOException e) { 

                                                       client.close(); 

                                                       System.out.println("2异常无连接aaaaaa"); 

                                           } 

                                  } else { 

                                            System.out.println("连接断开======="); 

                                 } 

                   } 


 } 

读数据需要单独的线程,如: 

while (true) { 

                                                     while (scanner.hasNext()) { 

                                                                 mess = scanner.next(); 

                                                                 

                                                                try { 

                                                                            server.server_fasong(mess); 

                                                                } catch (Exception e) { 

                                                                           // TODO Auto-generated catch block                                                                            e.printStackTrace(); 

                                                                } 

                                            }       

                              } 

ok啦,这样既可以读又可以写啦