当前位置: 首页 > news >正文

网络IO

网络IO

阻塞模型

在之前网络通信都是阻塞模型

  • 客户端向服务端发出请求后,客户端会一直处于等待状态,直到服务器端返回结果或网络出现问题
  • 服务器端也是如此,在处理某个客户端A发来的请求时,另一个客户端B发来的请求会等待,直到服务器端的处理线程线程上一个请求的处理

在服务端使用ServerSocket来建立套接字,accept方法会进行阻塞等待客户端的连接

try(
        // 创建一个ServerSocket对象
        ServerSocket serverSocket = new ServerSocket(9090);
        // accept方法,返回Socket对象,这里会进行阻塞,应用程序向操作系统请求接收已准备好的客户端连接的数据信息
        Socket s = serverSocket.accept();
        // 获取输入流,这里读取数据也会阻塞
        InputStream is = s.getInputStream();
        // 输出流,给客户端返回消息
        OutputStream os = s.getOutputStream();
        InputStreamReader isr = new InputStreamReader(is);
        BufferedReader reader = new BufferedReader(isr);
){
    String str;
    while ((str = reader.readLine()) != null){
        System.out.print(str);
    }
    os.write("我已收到消息".getBytes());
    
catch (IOException e){
    e.printStackTrace();
}
serverSocket.accept()阻塞

服务器端发起一个accept动作,询问操作系统是否有新的Socket套接字信息从端口发送过来,如果没有则serverSocket.accept()会一直等待

阻塞模型的问题:

  • 同一时间,服务器只能接收一个客户端的请求信息,第二个客户端需要等待服务器接收完第一个请求数据后才会被接收
  • 服务器一次只能处理一个客户端请求,处理完成并返回后才能进行第二次请求的处理

多线程阻塞模型

由于阻塞模型的弊端,高并发时会导致请求太慢,所以提出了使用多线程来解决上述阻塞问题

  • 服务器收到客户端A的请求后,开启线程去进行数据处理。主线程可以继续接收客户端B的请求

但是这样在进行serverSocket.accept();操作时还是单线程运行,只有业务处理才会使用多线程,对于接收数据的并发能力并没有提升

同步非阻塞模型

这里先说一下同步和非同步的概念

同步和非同步是操作系统级别的,主要描述操作系统在收到程序请求网络IO操作后,如果网络IO资源没有准备好,该如何响应程序

  • 同步IO不响应程序,直到网络IO资源准备好
  • 非同步IO返回一个标记,当网络IO资源准备好后,用事件机制通知给程序

再说一下阻塞和非阻塞的概念

阻塞和非阻塞是程序级别的,主要描述程序请求操作系统IO操作后,如果网络IO资源没有准备好,程序如何处理

  • 阻塞IO会进行等待
  • 非阻塞IO会继续执行,且使用线程一直轮询,直到IO资源准备好
{
        boolean flag = true;
        try {
            ServerSocket serverSocket = new ServerSocket(6666);
            // 使用超时时间来设置为非阻塞状态,超过该时间会抛出SocketTimeoutException
            serverSocket.setSoTimeout(100);

            while (true){
                Socket socket = null;
                try{
                    // 设置了超时时间后accept就不会阻塞了
                    socket  = serverSocket.accept();
                } catch (SocketTimeoutException e){
                    synchronized (obj){   // 100ms内没有接收到任何数据,可以在这里做一些别的操作
                        System.out.println("没接收到数据,先歇一歇吧");
                        try {
                            obj.wait(10);
                        } catch (InterruptedException interruptedException) {
                            interruptedException.printStackTrace();
                        }
                    }
                    continue;

                }
              // 开线程处理数据
                new Thread(socket).start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

serverSocket.setSoTimeout可以使accept方法不一直阻塞,而是到了超时时间后抛出SocketTimeoutException异常,此时就可以用主线程做别的事情了,虽然实际还是使用的accept阻塞模型,但是有所改善

多路复用模型

多路复用模型(也就是NIO)不在使用操作系统级别的同步IO,目前主要实现有select、poll、epoll、kqueue

{
    ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
    Selector selector = Selector.open();
    ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
    // 设置为非阻塞
    serverSocketChannel.configureBlocking(false);
    // 绑定8080端口
    serverSocketChannel.bind(new InetSocketAddress(8080));

    // 注册监听的事件
    // ServerSocketChannel只能注册OP_ACCEPT
    // SocketChannel可注册OP_READ、OP_WRITE、OP_CONNECT
    serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);


    while(true){
        // 询问selector中准备好的事件
        selector.select();
        // 获取到上述询问拿到的事件类型
        Set<SelectionKey> selectionKeys =  selector.selectedKeys();
        Iterator<SelectionKey> iterator = selectionKeys.iterator();
        while (iterator.hasNext()){
            SelectionKey selectionKey = iterator.next();
            if(selectionKey.isAcceptable()){
                ServerSocketChannel ssc = (ServerSocketChannel) selectionKey.channel();
                // 接收到服务端的请求
                SocketChannel sc = ssc.accept();
                sc.configureBlocking(false);
                sc.register(selector,SelectionKey.OP_READ);
                // 处理过了就要移除掉,否则再次select()还会拿到该事件
                iterator.remove();
            } else if(selectionKey.isReadable()){
                SocketChannel sc = (SocketChannel) selectionKey.channel();
                byteBuffer.clear();
                int n = sc.read(byteBuffer);
                if(n > 0){
                    byteBuffer.flip();
                    Charset charset = StandardCharsets.UTF_8;
                    String message = String.valueOf(charset.decode(byteBuffer).array());
                    System.out.println(message);
                }
                sc.register(selector,SelectionKey.OP_WRITE);
                iterator.remove();
            } else if(selectionKey.isWritable()){
                SocketChannel sc = (SocketChannel) selectionKey.channel();
                ByteBuffer buffer = ByteBuffer.allocate(1024);
                buffer.put("已接收到消息".getBytes());
                buffer.flip();
                sc.write(buffer);
                iterator.remove();
            }
        }
    }

}

多路复用显然绕过了accept方法的阻塞问题,使得操作系统可以在一个端口上能够同时接收多个客户端的IO事件

https://zhhll.icu/2022/java基础/IO/4.网络IO/

本文由 mdnice 多平台发布

相关文章:

网络IO

网络IO 阻塞模型 在之前网络通信都是阻塞模型 客户端向服务端发出请求后&#xff0c;客户端会一直处于等待状态&#xff0c;直到服务器端返回结果或网络出现问题 服务器端也是如此&#xff0c;在处理某个客户端A发来的请求时&#xff0c;另一个客户端B发来的请求会等待&#xf…...

数据库管理-第115期 too many open files(202301107)

数据库管理-第115期 too many open files&#xff08;202301107&#xff09; 这是我上周末帮朋友站台过程中处理的一个问题。 1 背景 其实这是别人搭的一个使用CentOS 7.8系统安装的一套11.2.0.4&#xff08;无补丁&#xff09;的双节点RAC&#xff0c;用于迁移以前运行在So…...

一行命令让你的服务器命令行亮起来!!!!

if [ "$(whoami)" "root" ]; then echo "PS1${debian_chroot:($debian_chroot)}\[\033[01;32m\]\u\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]# " >> /root/.bashrc; source /root/.bashrc; echo "已为root用户设置提示符以#结尾…...

线性代数(二)| 行列式性质 求值 特殊行列式 加边法 归纳法等多种方法

文章目录 1. 性质1.1 重要性质梳理1.1.1 转置和初等变换1.1.2加法行列式可拆分1.1.3 乘积行列式可拆分 1.2 行列式性质的应用1.2.1 简化运算1.2.2 将行列式转换为&#xff08;二&#xff09;中的特殊行列式 2 特殊行列式2.1 上三角或下三角行列式2.2 三叉行列式2.3 行列式行和&…...

OpenCV入门7:图像形态学变换

形态学是一种针对图像形状和结构进行操作和分析的图像处理方法。在OpenCV中&#xff0c;提供了一些函数和方法用于执行形态学操作。下面将介绍一些常见的形态学操作及其在OpenCV中的实现方式。 膨胀&#xff08;Dilation&#xff09;&#xff1a; 膨胀操作可以扩展图像中的边…...

Apache Storm 2.5.0 集群安装与配置

1、下载Apache Storm 2.5.0 https://mirrors.tuna.tsinghua.edu.cn/apache/storm/apache-storm-2.5.0/ 2、准备3台服务器 192.168.42.139 node1 192.168.42.140 node1 192.168.42.141 node2 3、配置host [rootnode1 ~]# cat /etc/hosts 127.0.0.1 localhost localhost…...

Android-将编码的base64图像,添加水印,转换成File存储到手机

一、将图片file转换成bitmap Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath()); 二、给图片添加水印 String[] content = new String[]{"纬度:" + latitude, "经度:" + longitude, "地址:" + signAddress, "时间:&…...

AI 绘画 | Stable Diffusion 图生图

图生图简介 Stable Diffusion 不仅可以文生图&#xff0c;还可以图生图。文生图就是完全用提示词文本去生成我们想要图片&#xff0c;但是很多时候会有词不达意的感觉。就像我们房子装修一样&#xff0c;我们只是通过文字描述很难表达出准确的想要的装修效果&#xff0c;如果能…...

Nat. Med. | 基于遗传学原发部位未知癌症的分类和治疗反应预测

今天为大家介绍的是来自Alexander Gusev团队的一篇论文。原发部位未知癌症&#xff08;Cancer of unknown primary&#xff0c;CUP&#xff09;是一种无法追溯到其原发部位的癌症&#xff0c;占所有癌症的3-5&#xff05;。CUP缺乏已建立的靶向治疗方法&#xff0c;导致普遍预后…...

RocketMQ如何安全的批量发送消息❓

优点&#xff1a; 批量发送消息可以提高rocketmq的生产者性能和吞吐量。 使用场景: 发送大量小型消息时&#xff1b;需要降低消息发送延迟时&#xff1b;需要提高生产者性能时&#xff1b; 注意事项&#xff1a; 消息列表的大小不能超过broker设置的最大消息大小;消息列表…...

计算机视觉与深度学习 | 基于视觉惯性紧耦合的SLAM后端优化算法

===================================================== github:https://github.com/MichaelBeechan CSDN:https://blog.csdn.net/u011344545 ===================================================== 基于视觉惯性紧耦合的SLAM后端优化算法 引言视觉惯性联合初始化非线性优…...

GDI+ 绘制透明图

目录 一、GDI+ 准备工作 1、线程中添加GDI+支持 2、Gdiplus::Bitmap 1)、从文件创建位图...

【Java】IntelliJ IDEA使用JDBC连接MySQL数据库并写入数据

目录 0 准备工作1 创建Java项目2 添加JDBC 驱动程序3 创建数据库连接配置文件4 创建一个 Java 类来连接和操作数据库5 运行应用程序 在 IntelliJ IDEA 中连接 MySQL 数据库并将数据存储在数据表中&#xff0c;使用 Java 和 JDBC&#xff08;Java Database Connectivity&#xf…...

Linux Hadoop平台伪分布式安装

Linux Hadoop 伪分布式安装 1. JDK2. Hadoop3. MysqlHive3.1 Mysql8安装3.2 Hive安装 4. Spark4.1 Maven安装4.2 Scala安装4.3 Spark编译并安装 5. Zookeeper6. HBase 版本概要&#xff1a; jdk&#xff1a; jdk-8u391-linux-x64.tar.gzhadoop&#xff1a;hadoop-3.3.1.tar.gzh…...

【STM32-DSP库的使用】基于Keil5 + STM32CubeMX 手动添加、库添加方式

STM32-DSP库的使用 一.CMSIS-DSP1.1 DSP库简介1.2 支持的函数类别1.3 宏定义 二、操作2.1 STM32CubeMX 配置基本工程2.2 Lib库的方式实现(推荐)2.3 手动添加DSP文件&#xff08;可以下载官方最新库&#xff0c;功能齐全&#xff09; 三、MFCC测试DSP加速效果 为验证语音识别MFC…...

createElement的用法

目录 一&#xff1a;介绍 二&#xff1a;语法与例子 1、语法 2、一些例子 例1&#xff1a; 例2&#xff1a; 例3&#xff1a; 3、第二种写法 一&#xff1a;介绍 document.createElement()是在对象中创建一个对象&#xff0c;要与appendChild() 或 insertBefore()方法…...

Mabitys总结

一、ORM ORM(Object/Relation Mapping)&#xff0c;中文名称&#xff1a;对象/关系 映射。是一种解决数据库发展和面向对象编程语言发展不匹配问题而出现的技术。 使用JDBC技术时&#xff0c;手动实现ORM映射&#xff1a; 使用ORM时&#xff0c;自动关系映射&#xff1a; &am…...

JAVA安全之Log4j-Jndi注入原理以及利用方式

什么是JNDI&#xff1f; JDNI&#xff08;Java Naming and Directory Interface&#xff09;是Java命名和目录接口&#xff0c;它提供了统一的访问命名和目录服务的API。 JDNI主要通过JNDI SPI&#xff08;Service Provider Interface&#xff09;规范来实现&#xff0c;该规…...

Spring源码系列-框架中的设计模式

简单工厂 实现方式&#xff1a; BeanFactory。Spring中的BeanFactory就是简单工厂模式的体现&#xff0c;根据传入一个唯一的标识来获得Bean对象&#xff0c;但是否是在传入参数后创建还是传入参数前创建这个要根据具体情况来定。 实质&#xff1a; 由一个工厂…...

数据的读取和保存-MATLAB

1 序言 在进行数据处理时&#xff0c;经常需要写代码对保存在文件中的数据进行读取→处理→保存的操作&#xff0c;流程图如下&#xff1a; 笔者每次在进行上述操作时&#xff0c;都需要百度如何“选中目标文件”以及如何“将处理好的数据保存到目标文件中”&#xff0c;对这一…...

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来

一、破局&#xff1a;PCB行业的时代之问 在数字经济蓬勃发展的浪潮中&#xff0c;PCB&#xff08;印制电路板&#xff09;作为 “电子产品之母”&#xff0c;其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透&#xff0c;PCB行业面临着前所未有的挑战与机遇。产品迭代…...

深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法

深入浅出&#xff1a;JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中&#xff0c;随机数的生成看似简单&#xff0c;却隐藏着许多玄机。无论是生成密码、加密密钥&#xff0c;还是创建安全令牌&#xff0c;随机数的质量直接关系到系统的安全性。Jav…...

(二)TensorRT-LLM | 模型导出(v0.20.0rc3)

0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述&#xff0c;后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作&#xff0c;其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...

使用分级同态加密防御梯度泄漏

抽象 联邦学习 &#xff08;FL&#xff09; 支持跨分布式客户端进行协作模型训练&#xff0c;而无需共享原始数据&#xff0c;这使其成为在互联和自动驾驶汽车 &#xff08;CAV&#xff09; 等领域保护隐私的机器学习的一种很有前途的方法。然而&#xff0c;最近的研究表明&…...

[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...

Linux云原生安全:零信任架构与机密计算

Linux云原生安全&#xff1a;零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言&#xff1a;云原生安全的范式革命 随着云原生技术的普及&#xff0c;安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测&#xff0c;到2025年&#xff0c;零信任架构将成为超…...

BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践

6月5日&#xff0c;2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席&#xff0c;并作《智能体在安全领域的应用实践》主题演讲&#xff0c;分享了在智能体在安全领域的突破性实践。他指出&#xff0c;百度通过将安全能力…...

AI编程--插件对比分析:CodeRider、GitHub Copilot及其他

AI编程插件对比分析&#xff1a;CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展&#xff0c;AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者&#xff0c;分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...

CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)

漏洞概览 漏洞名称&#xff1a;Apache Flink REST API 任意文件读取漏洞CVE编号&#xff1a;CVE-2020-17519CVSS评分&#xff1a;7.5影响版本&#xff1a;Apache Flink 1.11.0、1.11.1、1.11.2修复版本&#xff1a;≥ 1.11.3 或 ≥ 1.12.0漏洞类型&#xff1a;路径遍历&#x…...

使用Spring AI和MCP协议构建图片搜索服务

目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式&#xff08;本地调用&#xff09; SSE模式&#xff08;远程调用&#xff09; 4. 注册工具提…...