java NIO网络通信编程

来源:互联网 发布:java 双亲委派模型 编辑:程序博客网 时间:2024/05/17 20:12

之前使用传统IO写网络编程的时候,一般都是想这样开个主线程这样写服务器端:

  while(true){        ServerSocket serverSocket=new ServerSocket(8080);        Socket socket=serverSocket.accept();
        /*生成子线程处理新socket*/        }

这样的话每有一个新请求的连接,我们都要新建一个线程去处理该连接,而且当该连接长时间无响应的时候,该线程也需要一直等待,十分浪费资源。为了解决这个问题,jdk为我们提供了基于通道的非阻塞的网络通信方式:ServerSocketChannel和SocketChannel.

基于通道的服务器端一般是这样写的:

    
   Selector selector= Selector.open();        ServerSocketChannel serverSocketChannel=ServerSocketChannel.open();        serverSocketChannel.bind(new InetSocketAddress(8080));        serverSocketChannel.configureBlocking(false);//设置成非阻塞式状态        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);//向选择器注册监听连接功能        while(true){            if (selector.select()>0){                Iterator<SelectionKey> iterator=selector.selectedKeys().iterator();                while(iterator.hasNext()){                    SelectionKey selectionKey= iterator.next();                   if (selectionKey.isAcceptable()){                       //如果有新的连接                       SocketChannel socketChannel=((ServerSocketChannel)selectionKey.channel()).accept();                       socketChannel.register(selector,SelectionKey.OP_READ);                   }                   if (selectionKey.isReadable()){                        //如果有通道可读                   }
                   if(selectionKey.isWriteable()){
                       //如果有通道可写 
                   }                }            }        }
其中Selector顾名思义就是一个选择器,我们的服务端套接字通道和客户端套接字通道都要向其注册,表示我们要接受哪些事件的通知,比如
       serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
就代表了如果有新的连接进来就要通知我。如何拿到这个通知呢?通过selector的select()方法,我们可以拿到通知的所有事件,该方法是阻塞式的,意思是如果没有新的通知

的话就一直等待。当有新的事件通知时,我们就可以根据事件的类型去处理请求了。有一点需要注意,虽然我们不需要再为每一个socket单独开一个线程了,但是由于处理事件时可能耗时很大(如上传电影),所以我们也需要启动单独的线程去响应事件,也就是说,线程不再服务于socket,而是服务于事件(选择性的),只要事件一结束,线程就停止了

     客户端的代码就没什么好说的了:

        Selector selector=Selector.open();        SocketChannel socketChannel=SocketChannel.open(new InetSocketAddress("172.0.0.1",8080));        socketChannel.register(selector,SelectionKey.OP_READ);

这些基本上就是 NIO 的网络通信原型了。



 
原创粉丝点击