【网络编程(二)】NIO快速入门

NIO

Java NIO 三大核心组件

  1. Buffer(缓冲区):每个客户端连接都会对应一个Buffer,读写数据通过缓冲区读写。
  2. Channel(通道):每个channel用于连接Buffer和Selector,通道可以进行双向读写。
  3. Selector(选择器):一个选择器对应多个通道,用于监听多个通道的事件。Selector可以监听所有的channel是否有数据要读取,当某个channel有数据时,就去处理,所有channel都没有数据时,线程可以去执行其他任务。

image-20210916114642170

使用 NIO 模型操作 Socket 步骤:

  1. 创建 ServerSocketChannel 服务器;
  2. 创建多路复用器 Selector(每个操作系统创建出来的是不一样的 ,Windows创建的是 WindowsSelectorImpl)
  3. ServerSocketChannel 将建立连接事件注册到 Selector中(register 方法往 EPollArrayWrapper 中添加元素)
  4. 处理事件
    1. 如果是建立连接事件,则把客户端的读写请求也注册到Selector中;
    2. 如果是读写事件则按业务处理。

案例代码:

public class NioServer {

    public static void main(String[] args) throws IOException {
        // 创建服务器
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.bind(new InetSocketAddress(8888));
        serverSocketChannel.configureBlocking(false); // 配置成非阻塞式的channel
        // 创建一个IO多路复用选择器
        Selector selector = Selector.open();
        // 注册
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

        while (true) {
            // 阻塞的方法,返回值代表发生事件的通道的个数
            // 返回值 0 超时
            // -1 错误
            // select方法可以传递超时时间,如果不传的话是timeout最后会为-1表示不会超时
            selector.select();// 如果不设的话客户端不操作会一直阻塞在这
            // 只要走到这里,必然说明,发送了事情,有可读可写可连接的channel
            Set<SelectionKey> selectionKeys = selector.selectedKeys();
            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));
                    System.out.println("某某客户端连接来啦");
                }

                if (selectionKey.isReadable()) {
                    SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
                    ByteBuffer buffer = (ByteBuffer) selectionKey.attachment();
                    buffer.clear();
                    int read = socketChannel.read(buffer);
                    if (read == -1) { // 如果是可读事件,然后又没有数据,说明是客户端与服务器端的连接断开了,
                        // 这个时候我们关闭通道,不然选择器会一直监听通道,导致不必要的业务执行
                        socketChannel.close();
                    } else {
                        System.out.println(new String(buffer.array(), 0, buffer.position()));
                        System.out.println("有信息需要读取");
                    }
                }
                iterator.remove();
            }
        }

    }
}

doSelect 方法是由 WindowsSelectorImpl 类去实现的,这是select方法最后执行的方法,因为加了互斥锁,也是为什么说这里同步阻塞的原因。
在这里插入图片描述

俩问题:

  • 当 Selector.select() 方法返回后,它会返回一组 SelectionKey 对象,这些对象代表了已经就绪的 I/O 通道,即对应的文件描述符上有事件发生。这些 SelectionKey 对象Key用来处理对应的事件。但是,如果不将已经处理过的 SelectionKey 对象从 Selector 中删除,下次调用 Selector.select() 方法时,这些已经处理过的 SelectionKey 对象扔然会被返回,导致多余的事件处理,影响性能问题。

  • 删除的话,我们可以通过 SelectionKey.cancel() 方法来实现,并且使得对应的通道(即文件描述符)不再被Selector监视。(这是有问题的,这样的话以后这个 SelectionKey 就不会再被监听了)可以在迭代器使用的时候对其进行删除。

Netty 封装好后就帮我们解决了这种问题,不会出现事件处理完后续还会一直处理的现象。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/79005.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux下Docker安装及卸载

文章目录 Linux下Docker安装及卸载1 Docker安装及卸载1.1 安装前准备1.2 安装docker软件2.4.3 启动docker2.2.4 测试2.2.5 卸载 Linux下Docker安装及卸载 1 Docker安装及卸载 官方网址&#xff1a;https://docs.docker.com/engine/install/centos/ 1.1 安装前准备 确定你是C…

zookeeper安装配置采坑流程

安装 wget https://dlcdn.apache.org/zookeeper/zookeeper-3.8.2/apache-zookeeper-3.8.2-bin.tar.gz解压&#xff1a; tar -zxvf apache-zookeeper-3.8.2-bin.tar.gz如下 bin目录下文件是可执行文件 conf目录文件是配置文件 修改zoo.cfg&#xff08;复制zoo_sample&#x…

【学习FreeRTOS】第12章——FreeRTOS时间管理

1.FreeRTOS系统时钟节拍 FreeRTOS的系统时钟节拍计数器是全局变量xTickCount&#xff0c;一般来源于系统的SysTick。在STM32F1中&#xff0c;SysTick的时钟源是72MHz/89MHz&#xff0c;如下代码&#xff0c;RELOAD 9MHz/1000-1 8999&#xff0c;所以时钟节拍是1ms。 portNV…

jvm类文件结构

一 概述 在 Java 中&#xff0c;JVM 可以理解的代码就叫做字节码&#xff08;即扩展名为 .class 的文件&#xff09;&#xff0c;它不面向任何特定的处理器&#xff0c;只面向虚拟机。Java 语言通过字节码的方式&#xff0c;在一定程度上解决了传统解释型语言执行效率低的问题…

学渣的愤怒!自考本科能不能不考英语和数学?

英语和高数哪个更难&#xff1f; 这是自考生们最头大的两个科目。 自考高数有多难&#xff1f; 高数主要有微积分、线性代数和概率论三个部分。 其中微积分是基础、也是重要的一部分&#xff0c;不仅涉及到很多抽象概念和符号运算&#xff0c;还需要具备良好的计算能力和逻…

简单的洗牌算法

目录 前言 问题 代码展现及分析 poker类 game类 Text类 前言 洗牌算法为ArrayList具体使用的典例&#xff0c;可以很好的让我们快速熟系ArrayList的用法。如果你对ArrayList还不太了解除&#xff0c;推荐先看本博主的ArrayList的详解。 ArrayList的详解_WHabcwu的博客-CSD…

C++笔记之单例模式

C笔记之单例模式 参考笔记&#xff1a;C笔记之call_once和once_flag code review 文章目录 C笔记之单例模式1.返回实例引用2.返回实例指针3.单例和智能指针share_ptr结合4.单例和std::call_once结合5.单例和std::call_once、unique_ptr结合 1.返回实例引用 代码 #include <…

数据结构之队列详解(包含例题)

一、队列的概念 队列是一种特殊的线性表&#xff0c;特殊之处在于它只允许在表的前端&#xff08;front&#xff09;进行删除操作&#xff0c;而在表的后端&#xff08;rear&#xff09;进行插入操作&#xff0c;和栈一样&#xff0c;队列是一种操作受限制的线性表。进行插入操…

亿发创新中医药信息化解决方案,自动化煎煮+调剂,打造智能中药房

传统中医药行业逐步复兴&#xff0c;同时互联网科技和人工智能等信息科技助力中医药行业逐步实现数字化转型。利用互联网、物联网、大数据等科技&#xff0c;实现现代科学与传统中医药的结合&#xff0c;提供智能配方颗粒调配系统、中药自动化调剂系统、中药煎配智能管理系统、…

【Docker报错】docker拉取镜像时报错:no such host

报错信息 [rootSoft soft]# docker pull mysql Using default tag: latest Error response from daemon: Head "https://registry-1.docker.io/v2/library/mysql/manifests/latest": dial tcp: lookup registry-1.docker.io on 192.168.80.2:53: no such host解决方法…

Leetcode-每日一题【剑指 Offer 28. 对称的二叉树】

题目 请实现一个函数&#xff0c;用来判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样&#xff0c;那么它是对称的。 例如&#xff0c;二叉树 [1,2,2,3,4,4,3] 是对称的。 1 / \ 2 2 / \ / \ 3 4 4 3 但是下面这个 [1,2,2,null,3,null,3] 则不是镜像对称…

Android 网络编程-网络请求

Android 网络编程-网络请求 文章目录 Android 网络编程-网络请求一、主要内容二、开发网络请求前的基本准备1、查看需要请求的网址是否有效&#xff08;1&#xff09;通过网页在线验证&#xff08;2&#xff09;使用专用window网咯请求工具&#xff08;3&#xff09;编写app代码…

多维时序 | MATLAB实现WOA-CNN-BiGRU-Attention多变量时间序列预测

多维时序 | MATLAB实现WOA-CNN-BiGRU-Attention多变量时间序列预测 目录 多维时序 | MATLAB实现WOA-CNN-BiGRU-Attention多变量时间序列预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 多维时序 | MATLAB实现WOA-CNN-BiGRU-Attention多变量时间序列预测 1.程…

LVS负载均衡集群-NAT模式部署

集群 集群&#xff1a;将多台主机作为一个整体&#xff0c;然后对外提供相同的服务 集群使用场景&#xff1a;高并发的场景 集群的分类 1.负载均衡器集群 减少响应延迟&#xff0c;提高并发处理的能力 2&#xff0c;高可用集群 增强系统的稳定性可靠性&…

LeetCode 141.环形链表

文章目录 &#x1f4a1;题目分析&#x1f4a1;解题思路&#x1f514;接口源码&#x1f4a1;深度思考❓思考1❓思考2 题目链接&#x1f449; LeetCode 141.环形链表&#x1f448; &#x1f4a1;题目分析 给你一个链表的头节点 head &#xff0c;判断链表中是否有环。 如果链表中…

Echarts地图-全国主要城市空气质量【亲测有效】

参考&#xff1a; Echarts官网实例 效果&#xff1a; 需要通过ajax的方式获取json数据: {"code":100,"msg":"处理成功&#xff01;","extend":{"items":[{"name":"三亚","value":52},{&qu…

适合程序员的DB性能测试工具 JMeter

背景 1、想要一款既要能压数到mysql&#xff0c;又要能压数到postGre&#xff0c;还要能压数到oracle的自动化工具 2、能够很容易编写insert sql&#xff08;因为需要指定表和指定字段类型压数据&#xff09;&#xff0c;然后点击运行按钮后&#xff0c;就能直接运行&#xff…

精彩回顾 | 迪捷软件出席2023ATC汽车电子与软件技术周

2023年8月18日&#xff0c;由ATC汽车技术会议主办&#xff0c;上海市集成电路行业协会支持的“2023ATC汽车电子与软件技术周”在上海市圆满落幕。迪捷软件上海参展之行圆满收官。 ▲开幕式 本次峰会汇聚了整车厂、汽车零部件集团、软硬件方案提供商、软件工具供应商、软件测试…

利用console提高写bug的效率

前端面试题库 &#xff08;面试必备&#xff09; 推荐&#xff1a;★★★★★ 地址&#xff1a;前端面试题库 自从入坑前端后&#xff0c;日常写bug就没离开过console。 要说用得多&#xff0c;不如说是console.log用得多&#xff0c;console.warn和console.erro…

shell脚本基础

目录 前言 一、概述 &#xff08;一&#xff09;、shell脚本基础概念 &#xff08;二&#xff09;、shell的类型 二、Shell变量 &#xff08;一&#xff09;、组成 1.变量名 2.变量值 &#xff08;二&#xff09;、类型 1.系统内置变量&#xff08;环境变量&#xff09; 2.自定…