当前位置: 首页 > 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;对这一…...

内存分配函数malloc kmalloc vmalloc

内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...

Prompt Tuning、P-Tuning、Prefix Tuning的区别

一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...

【入坑系列】TiDB 强制索引在不同库下不生效问题

文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...

数据链路层的主要功能是什么

数据链路层&#xff08;OSI模型第2层&#xff09;的核心功能是在相邻网络节点&#xff08;如交换机、主机&#xff09;间提供可靠的数据帧传输服务&#xff0c;主要职责包括&#xff1a; &#x1f511; 核心功能详解&#xff1a; 帧封装与解封装 封装&#xff1a; 将网络层下发…...

【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具

第2章 虚拟机性能监控&#xff0c;故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令&#xff1a;jps [options] [hostid] 功能&#xff1a;本地虚拟机进程显示进程ID&#xff08;与ps相同&#xff09;&#xff0c;可同时显示主类&#x…...

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列&#xff0c;以便知晓哪些列包含有价值的数据&#xff0c;…...

Python 包管理器 uv 介绍

Python 包管理器 uv 全面介绍 uv 是由 Astral&#xff08;热门工具 Ruff 的开发者&#xff09;推出的下一代高性能 Python 包管理器和构建工具&#xff0c;用 Rust 编写。它旨在解决传统工具&#xff08;如 pip、virtualenv、pip-tools&#xff09;的性能瓶颈&#xff0c;同时…...

iOS性能调优实战:借助克魔(KeyMob)与常用工具深度洞察App瓶颈

在日常iOS开发过程中&#xff0c;性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期&#xff0c;开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发&#xff0c;但背后往往隐藏着系统资源调度不当…...

Web后端基础(基础知识)

BS架构&#xff1a;Browser/Server&#xff0c;浏览器/服务器架构模式。客户端只需要浏览器&#xff0c;应用程序的逻辑和数据都存储在服务端。 优点&#xff1a;维护方便缺点&#xff1a;体验一般 CS架构&#xff1a;Client/Server&#xff0c;客户端/服务器架构模式。需要单独…...

动态规划-1035.不相交的线-力扣(LeetCode)

一、题目解析 光看题目要求和例图&#xff0c;感觉这题好麻烦&#xff0c;直线不能相交啊&#xff0c;每个数字只属于一条连线啊等等&#xff0c;但我们结合题目所给的信息和例图的内容&#xff0c;这不就是最长公共子序列吗&#xff1f;&#xff0c;我们把最长公共子序列连线起…...