java 网络编程 篇二(nio)

篇一 我们讲到了bio 在高并发场景下,存在创建线程数过多的问题,因此 nio 应运而生。

nio 同步非阻塞io ,主要针对网络io 来说, 下图主要为非阻塞模型io 

nio 相较于bio 采用的是事件驱动机制,通过多路复用器监听客户端的连接,读取,写入.. 事件,在事件触发时,做相应的业务处理。nio 有如下几个核心概念:

1. channel 通道,即为数据传输的通道,与bio 不同,通道为双向的,打个简单的比方,

2. byteBuffer 缓冲区, 和通道一一对应,缓冲区即为一块内存区域,和我们的 创建的ArrayList ,map 内存区域是一样的,

打个简单的比方,channel 类似于铁轨,byteBuffer 类似于火车,channel 可以往byteBuffer 读写数据,byteBuffer也可以从channel读写数据,最终我们的程序是从byteBuffer 里边读写数据。

3. selector 多路复用器,这个为nio 里边的事件驱动和线程的复用的核心组件,selector 通过监听服务端的连接事件,将客户端连接的channel 注册到selector 中,让后轮询注册的channel,监听channel 注册 的事件,从而使得一个线程可以管理多channel通道,从而减少了服务端的线程创建,

下图为一个简单的nio 服务端,只有读取客户端发送的数据,将其打印在服务端的及控制台上。有需要的朋友可以参考

public class NioServer {

    public void run() throws IOException {
        //服务端监听Client 连接的socket todo  异常先抛出去
        ServerSocketChannel serverSocketChannel=ServerSocketChannel.open();
        //多路复用器
        Selector selector=Selector.open();
        //绑定端口
        serverSocketChannel.bind(new InetSocketAddress(8080));

        // 设置serverSocketChannel 为非阻塞
        serverSocketChannel.configureBlocking(false);

        //往selecttor 注册连接事件监听
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        // 监听连接事件
        while (true){
            int readChannel = selector.select();
            if(readChannel == 0){
                System.out.println(" 暂无客户端连接 ");
                continue;
            }
            Set<SelectionKey> selectionKeys = selector.selectedKeys();
            System.out.println("长度:"+selectionKeys.size());
            Iterator<SelectionKey> iterator = selectionKeys.iterator();
            while (iterator.hasNext()){
                SelectionKey selectionKey=iterator.next();
                //处理连接事件
                if(selectionKey.isAcceptable()){
                    //获取客户端连接
                    SocketChannel socketChannel=serverSocketChannel.accept();
                    socketChannel.configureBlocking(false);
                    socketChannel.register(selector,SelectionKey.OP_READ, ByteBuffer.allocate(1024));
                }
                if(selectionKey.isReadable()){
                    //获取socket channel
                    SocketChannel socketChannel= (SocketChannel) selectionKey.channel();
                    //获取绑定的ByteBuffer
                    ByteBuffer buffer = (ByteBuffer)selectionKey.attachment();
                    //将channel的数据读到byteBuffer 中
                    socketChannel.read(buffer);
                    //输出客户端发送的数据
                    System.out.println(" 客户端:"+new String(buffer.array()));
                }

                //移除已处理的事件避免channel的重复注册
                iterator.remove();
            }
        }
    }
    public static void main(String[] args) throws IOException {
        new NioServer().run();
    }

nio 还有许多可以值得挖掘的东西,类似于selector 轮询 epoll 空轮询,事件驱动,byteBuffer 数据结构,小编暂时也在学习。限于现在也是边学边分享,此篇幅暂时也无法做介绍。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值