java NIO网络通信编程

本文介绍了一种基于通道的非阻塞网络通信方式,利用ServerSocketChannel和SocketChannel替代传统IO模型,通过Selector实现高效的事件驱动处理机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

之前使用传统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 的网络通信原型了。

                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值