Java网络编程-深入理解BIO、NIO
深入理解BIO与NIO
BIO
BIO 为 Blocked-IO(阻塞 IO),在 JDK1.4 之前建立网络连接时,只能使用 BIO
使用 BIO 时,服务端会对客户端的每个请求都建立一个线程进行处理,客户端向服务端发送请求后,先咨询服务端是否有线程响应,如果没有就会等待或者被拒绝
BIO 基本使用代码:
服务端:
public class TCPServer {public static void main(String[] args) throws Exception {// 1.创建ServerSocket对象System.out.println("服务端 启动....");System.out.println("初始化端口 7777 ");ServerSocket ss = new ServerSocket(7777); //端口号while (true) {// 2.监听客户端Socket s = ss.accept(); //阻塞// 3.从连接中取出输入流来接收消息InputStream is = s.getInputStream(); //阻塞byte[] b = new byte[10];is.read(b);String clientIP = s.getInetAddress().getHostAddress();System.out.println(clientIP + "说:" + new String(b).trim());// 4.从连接中取出输出流并回话OutputStream os = s.getOutputStream();os.write("服务端回复".getBytes());// 5.关闭s.close();}}
}
客户端:
public class TCPClient {public static void main(String[] args) throws Exception {while (true) {// 1.创建Socket对象Socket s = new Socket("127.0.0.1", 7777);// 2.从连接中取出输出流并发消息OutputStream os = s.getOutputStream();System.out.println("请输入:");Scanner sc = new Scanner(System.in);String msg = sc.nextLine();os.write(msg.getBytes());// 3.从连接中取出输入流并接收回话InputStream is = s.getInputStream(); //阻塞byte[] b = new byte[20];is.read(b);System.out.println("客户端发送消息:" + new String(b).trim());// 4.关闭s.close();}}
}
BIO 缺点:
- Server 端会为客户端的每一个连接请求都创建一个新的线程进行处理,如果客户端连接请求数量太多,则会创建大量线程
NIO
从 JDK1.4 开始,Java 提供了一系列改进的输入/输出的新特性,被统称为 NIO(即 New IO),NIO 弥补了 BIO 的不足,在服务端不需要为客户端大量的请求而建立大量的处理线程,只需要用很少的线程就可以处理很多客户端请求
NIO 和 BIO 有着相同的目的和作用,但是它们的实现方式完全不同;
- BIO 以流的方式处理数据,而 NIO 以块的方式处理数据,块 IO 的效率比流 IO 高很多。
- NIO 是非阻塞式的,这一点跟 BIO 也很不相同,使用它可以提供非阻塞式的高伸缩性网络。
NIO 有三大核心部分:
- Channel通道
- Buffer缓冲区
- Selector选择器
使用 NIO 时,数据是基于 Channel 和 Buffer 进行操作的,数据从 Channel 被读取到 Buffer 或者相反,Selector 用于监听多个 Channel 通道的事件(连接事件、读写事件),通过 Selector 就可以实现单个线程来监听多个客户端通道
NIO 中的 Channel 用来建立到目标的一个连接,在 BIO 中流是单向的,例如 FileInputStream 只能进行读取操作,而在 NIO 中 Channel 是双向的,既可以读也可以写
NIO 工作流程图如下:Server 端通过单线程来监听多个客户端 Channel 通道中的事件并进行处理

NIO 使用示例
服务端:
public class NIOServer {public static void main(String[] args) throws Exception {// 1. 开启一个ServerSocketChannel通道ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();// 2. 开启一个Selector选择器Selector selector = Selector.open();// 3. 绑定端口号8888System.out.println("服务端 启动....");System.out.println("初始化端口 8888 ");serverSocketChannel.bind(new InetSocketAddress(8888));// 4. 配置非阻塞方式serverSocketChannel.configureBlocking(false);// 5. Selector选择器注册ServerSocketChannel通道,绑定连接操作serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);// 6. 循环执行:监听连接事件及读取数据操作while (true) {// 6.1 监控客户端连接:selecto.select()方法返回的是客户端的通道数,如果为0,则说明没有客户端连接。if (selector.select(2000) == 0) {System.out.println("服务端等待客户端连接中~");continue;}// 6.2 得到SelectionKey,判断通道里的事件Iterator<SelectionKey> keyIterator = selector.selectedKeys().iterator();// 遍历所有SelectionKeywhile (keyIterator.hasNext()) {SelectionKey key = keyIterator.next();// 客户端连接请求事件if (key.isAcceptable()) {System.out.println("服务端处理客户端连接事件:OP_ACCEPT");SocketChannel socketChannel = serverSocketChannel.accept();socketChannel.configureBlocking(false);// 服务端建立与客户端之间的连接通道 SocketChannel,并且将该通道注册到 Selector 中,监听该通道的读事件socketChannel.register(selector, SelectionKey.OP_READ, ByteBuffer.allocate(1024));}// 读取客户端数据事件if (key.isReadable()) {// 数据在通道中,先拿到通道SocketChannel channel = (SocketChannel) key.channel();// 取到一个缓冲区,nio读写数据都是基于缓冲区。ByteBuffer buffer = (ByteBuffer) key.attachment();// 从通道中将客户端发来的数据读到缓冲区channel.read(buffer);System.out.println("客户端数据长度:" + buffer.array().length);System.out.println("客户端发来数据:" + new String(buffer.array()));}// 6.3 手动从集合中移除当前key,防止重复处理keyIterator.remove();}}}
}
客户端:
public class NIOClient {public static void main(String[] args) throws Exception {// 1. 得到一个网络通道SocketChannel channel = SocketChannel.open();// 2. 设置非阻塞方式channel.configureBlocking(false);// 3. 提供服务器端的IP地址和端口号InetSocketAddress address = new InetSocketAddress("127.0.0.1", 8888);// 4. 连接服务器端,如果用connect()方法连接服务器不成功,则用finishConnect()方法进行连接if (!channel.connect(address)) {// 因为接需要花时间,所以用while一直去尝试连接。在连接服务端时还可以做别的事,体现非阻塞。while (!channel.finishConnect()) {// nio 作为非阻塞式的优势,如果服务器没有响应(不启动服务端),客户端不会阻塞,最后会报错,客户端尝试连接服务器连不上。System.out.println("客户端等待连接建立时,执行其他任务~");}}// 5. 得到一个缓冲区并存入数据String msg = "客户端发送消息:hello";ByteBuffer writeBuf = ByteBuffer.wrap(msg.getBytes());// 6. 发送数据channel.write(writeBuf);// 阻止客户端停止,否则服务端也会停止。System.in.read();}
}
AIO
JDK 7 引入了 Asynchronous IO,即 AIO,叫做异步不阻塞的 IO,也可以叫做 NIO2
在进行 IO 编程中,常用到两种模式:Reactor模式 和 Proactor 模式
- NIO采用 Reactor 模式,当有事件触发时,服务器端得到通知,进行相应的处理
- AIO采用 Proactor 模式,引入异步通道的概念,简化了程序编写,一个有效的请求才启动一个线程,它的特点是先由操作系统完成后,才通知服务端程序启动线程去处理,一般适用于连接数较多且连接时间较长的应用
相关文章:
Java网络编程-深入理解BIO、NIO
深入理解BIO与NIO BIO BIO 为 Blocked-IO(阻塞 IO),在 JDK1.4 之前建立网络连接时,只能使用 BIO 使用 BIO 时,服务端会对客户端的每个请求都建立一个线程进行处理,客户端向服务端发送请求后,…...
ShenYu网关注册中心之HTTP注册原理
文章目录 1、客户端注册流程1.1、读取配置1.1.1、用于注册的 HttpClientRegisterRepository1.1.2、用于扫描构建 元数据 和 URI 的 SpringMvcClientEventListener 1.2、扫描注解,注册元数据和URI1.2.1、构建URI并写入Disruptor1.2.2、构建元数据并写入Disruptor1.2.…...
探索GameFi:区块链与游戏的未来融合
在过去的几年里,区块链技术逐渐渗透到各个领域,为不同行业带来了前所未有的变革。其中,游戏行业成为了一个引人注目的焦点,而这种结合被称为GameFi,即游戏金融。GameFi不仅仅是一个概念,更是一场区块链和游…...
Windows下使用CMake编译lua
Lua 是一个功能强大、高效、轻量级、可嵌入的脚本语言。它支持程序编程、面向对象程序设计、函数式编程、数据驱动编程和数据描述。 Lua的官方网站上只提供了源码,需要使用Make进行编译,具体的编译方法为 curl -R -O http://www.lua.org/ftp/lua-5.4.6.…...
【C语言(十一)】
C语言内存函数 一、memcpy使用和模拟实现 void * memcpy ( void * destination, const void * source, size_t num ); • 函数memcpy从source的位置开始向后复制num个字节的数据到destination指向的内存位置。 • 这个函数在遇到 \0 的时候并不会停下来。 • 如果sourc…...
系统运行占用过高
1、CPU过高的问题排查 示例代码: public class Test { static class MyThread extends Thread { public void run() { // 死循环,消耗CPU int i 0; while (true) { i; } } } public static void main(String args[]) throws InterruptedException { ne…...
HTML---初识CSS
文章目录 前言一、pandas是什么?二、使用步骤 1.引入库2.读入数据总结 一.CSS概念 CSS是层叠样式表(Cascading Style Sheets)的缩写。它是一种用于描述HTML文档外观样式的标记语言。通过CSS,开发者可以在不改变HTML标记结构的情况…...
监控pod 容器外网请求网络带宽,过滤掉内网、基于k8spacket开发、prometheus开发export
首先安装k8spacket 安装k8spacket遇到问题,下载插件一直能不能下载成功,pod不能启动。所有手动下载处理。 helm repo add k8spacket https://k8spacket.github.io/k8spacket-helm-chart helm pull k8spacket/k8spacket打开values.yaml 文件 手动下载插…...
windows下docker环境安装
开启硬件虚拟化技术 win10中开启 Hyper-V Win10 下是否开启硬件虚拟化技术,在控制面板,启用 window 功能,找到 Hyper-V 选项,点勾选确认。如图: Windows 11 家庭中文版新增 Hyper-V选项 注意以下的解决方案来自win1…...
Python小程序 - 表格数值统计
题设:Excel表格中,计算如下图所示不同颜色(蓝、黄、桔)单元格值:各颜色填涂的单元格值的总和条件: - Excle表格中 - 分色标记,单元格有值 - 开始列(当前为D),…...
Unity | Shader基础知识(第一集:unity中最简单的shader)
目录 一、unity的shader 二、创建一个shader(在创建时,选前三种都可以) 三、内容解读 1.shader一直都在 2.我们写shader在写什么 四、没有被干预的shader(最简单的shader) 相关阅读 编写着色器概述 - Unity 手册…...
橘子学K8S01之容器中所谓的隔离
我们一直都在说容器就是一个沙盒,沙盒技术顾名思义就是像一个集装箱一样,把应用(服务,进程之类的)装起来的技术,这样每个进程在自己的沙盒中和其他的沙盒隔离开来,每个沙盒之间存在一个边界使得他们互不干扰࿰…...
利用svm进行模型训练
一、步骤 1、将文本数据转换为特征向量 : tf-idf 2、使用这些特征向量训练SVM模型 二、代码 from sklearn.model_selection import train_test_split from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.svm import SVC from sklearn.m…...
【Docker】WSL 2 上的 Docker 搭建和入门
▒ 目录 ▒ 🛫 导读开发环境 1️⃣ 安装安装Docker Desktop for Windows 2️⃣ 环境配置3️⃣ hello world第一次运行再次运行分析总结 📖 参考资料 🛫 导读 开发环境 版本号描述文章日期2023-12-14操作系统Win11 - 22H222621.2715WSL2 C:…...
pytorch环境配置
1.创建环境 conda create --name pytorch python3.11.5 2.激活环境 source activate pytorch 3.添加国内镜像源: conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/ conda config --add channels https://mirrors.tuna.tsin…...
电子眼+无人机构建平安城市视频防控监控方案
电子眼(也称为监控摄像机)可以通过安装在城市的不同角落,实时监控城市的各个地方。它们可以用于监测交通违法行为、监控公共场所的安全以及实时监测特定区域的活动情况。通过电子眼的应用,可以帮助警方及时发现并响应各类安全事件…...
mysql binlog_ignore_db参数的效果详解
我们知道 binlog 会记录数据库所有执行的 DDL 和 DML 语句(除了数据查询语句select、show等)。 我们可以在mysql配置文件中关闭binlog [mysqld] skip-log-bin注意默认情况下会记录所有库的操作,那么如果我们有另类需求,比如说只让某个库记录 binglog 或排除某个库记录…...
HI3559AV100和FPGA 7K690T的PCIE接口调试记录-续
上文https://blog.csdn.net/fzktongyong/article/details/134963814?spm1001.2014.3001.5501 上一篇文中PCIE实测速度和理论计算有较大偏差,经过尝试后有所提升。 1、提升效果 1)、RC写操作,实测速度817MB/s(410407&…...
vivado约束方法4
时序约束向导 定时约束向导确定合成或上缺少的定时约束实现的设计。它分析了网表、时钟网络连接和现有的定时限制,以便根据《超快设计方法指南》提供建议用于FPGA和SoC(UG949)。以下11涵盖了三类约束页面,然后是摘要。包括以下步…...
LeetBook学习-C语言-数组
1.数组的操作 1.1 读取元素 知道内存地址可以快速访问,时间复杂度为O(1) 1.2 查找元素 从首地址开始,逐个查找,最坏时间复杂度为O(N) 1.3 插入元素 插入元素,首先位置要腾空,而后执行插入操作。 1.4 删除元素 删除掉某…...
Python|GIF 解析与构建(5):手搓截屏和帧率控制
目录 Python|GIF 解析与构建(5):手搓截屏和帧率控制 一、引言 二、技术实现:手搓截屏模块 2.1 核心原理 2.2 代码解析:ScreenshotData类 2.2.1 截图函数:capture_screen 三、技术实现&…...
【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型
摘要 拍照搜题系统采用“三层管道(多模态 OCR → 语义检索 → 答案渲染)、两级检索(倒排 BM25 向量 HNSW)并以大语言模型兜底”的整体框架: 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后,分别用…...
【Python】 -- 趣味代码 - 小恐龙游戏
文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...
React Native 导航系统实战(React Navigation)
导航系统实战(React Navigation) React Navigation 是 React Native 应用中最常用的导航库之一,它提供了多种导航模式,如堆栈导航(Stack Navigator)、标签导航(Tab Navigator)和抽屉…...
Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...
安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件
在选煤厂、化工厂、钢铁厂等过程生产型企业,其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进,需提前预防假检、错检、漏检,推动智慧生产运维系统数据的流动和现场赋能应用。同时,…...
【网络安全产品大调研系列】2. 体验漏洞扫描
前言 2023 年漏洞扫描服务市场规模预计为 3.06(十亿美元)。漏洞扫描服务市场行业预计将从 2024 年的 3.48(十亿美元)增长到 2032 年的 9.54(十亿美元)。预测期内漏洞扫描服务市场 CAGR(增长率&…...
UDP(Echoserver)
网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法:netstat [选项] 功能:查看网络状态 常用选项: n 拒绝显示别名&#…...
系统设计 --- MongoDB亿级数据查询优化策略
系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log,共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题,不能使用ELK只能使用…...
PL0语法,分析器实现!
简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...
