NIO和BIO编程
一、网络通信编程基本常识
1、什么是Socket?
Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口,一般由操作系统提供。

2、短连接
短连接是指socket建立连接之后传输数据确定接收完后关闭连接
3、长连接
长连接是指建立socket连接后不管是否使用都保持连接
4、什么时候用长连接,短连接?
http1.1网上都开始向长连接演化,web网站成千上万的客户端使用短连接会更节省资源消耗,短连接频繁的通信会造成socket错误,而socket频繁的创建也会耗费系统资源
二、Java原生网络编程
1、原生JDK网络编程BIO
面向流的阻塞IO,
服务端(这种来一个客户端就创建一个线程的方式,如果客户端连接数量过多,内存资源消耗过多,造成系统崩溃)
public class Server {public static void main(String[] args) throws IOException {// 创建ServerSocket接收客户端连接对象ServerSocket serverSocket = new ServerSocket();// 绑定服务器监听端口serverSocket.bind(new InetSocketAddress(8888));System.out.println("start server...");while (true) {new Thread(new ServerTask(serverSocket.accept())).start();}}private static class ServerTask implements Runnable {private Socket socket = null;public ServerTask(Socket socket) {this.socket = socket;}@Overridepublic void run() {try(//实例化与客户端通信的输入输出流ObjectInputStream inputStream = new ObjectInputStream(socket.getInputStream());ObjectOutputStream outputStream = new ObjectOutputStream(socket.getOutputStream())){//接收客户端的输出,也就是服务器的输入String userName = inputStream.readUTF();System.out.println("Accept client message:"+userName);//服务器的输出,也就是客户端的输入outputStream.writeUTF("Hello,"+userName);outputStream.flush();}catch(Exception e){e.printStackTrace();}finally {try {socket.close();} catch (IOException e) {e.printStackTrace();}}}}
}// 单线程实现服务端连接(单线程服务端无法同时支持多个连接同时处理)
class ServerSingle {public static void main(String[] args) throws IOException {//服务端启动必备ServerSocket serverSocket = new ServerSocket();//表示服务端在哪个端口上监听serverSocket.bind(new InetSocketAddress(8888));System.out.println("Start Server ....");int connectCount = 0;try {while(true){Socket socket = serverSocket.accept();System.out.println("accept client socket ....total =" + ( ++connectCount));//实例化与客户端通信的输入输出流try(ObjectInputStream inputStream =new ObjectInputStream(socket.getInputStream());ObjectOutputStream outputStream =new ObjectOutputStream(socket.getOutputStream())){//接收客户端的输出,也就是服务器的输入String userName = inputStream.readUTF();System.out.println("Accept client message:"+userName);//服务器的输出,也就是客户端的输入outputStream.writeUTF("Hello,"+userName);outputStream.flush();}catch(Exception e){e.printStackTrace();}finally {try {socket.close();} catch (IOException e) {e.printStackTrace();}}}} finally {serverSocket.close();}}
}// 线程池的方式启动服务端(受线程数量影响,如果传输的数据过大 比如文件,占用时间过长的话,其它连接只能等待)
class ServerPool {private static ExecutorService executorService= Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());public static void main(String[] args) throws IOException {//服务端启动必备ServerSocket serverSocket = new ServerSocket();//表示服务端在哪个端口上监听serverSocket.bind(new InetSocketAddress(10001));System.out.println("Start Server ....");try{while(true){executorService.execute(new ServerTask(serverSocket.accept()));}}finally {serverSocket.close();}}//每个和客户端的通信都会打包成一个任务,交个一个线程来执行private static class ServerTask implements Runnable{private Socket socket = null;public ServerTask(Socket socket){this.socket = socket;}@Overridepublic void run() {//实例化与客户端通信的输入输出流try(ObjectInputStream inputStream =new ObjectInputStream(socket.getInputStream());ObjectOutputStream outputStream =new ObjectOutputStream(socket.getOutputStream())){//接收客户端的输出,也就是服务器的输入String userName = inputStream.readUTF();System.out.println("Accept client message:"+userName);//服务器的输出,也就是客户端的输入outputStream.writeUTF("Hello,"+userName);outputStream.flush();}catch(Exception e){e.printStackTrace();}finally {try {socket.close();} catch (IOException e) {e.printStackTrace();}}}}}
客户端
public class Client {public static void main(String[] args) throws IOException {Socket socket = null;ObjectOutputStream objectOutputStream = null;ObjectInputStream objectInputStream = null;InetSocketAddress inetSocketAddress = new InetSocketAddress("127.0.0.1", 8888);try {socket = new Socket();socket.connect(inetSocketAddress);System.out.println("connect server success");objectOutputStream = new ObjectOutputStream(socket.getOutputStream());objectInputStream = new ObjectInputStream(socket.getInputStream());System.out.println("ready send message");objectOutputStream.writeUTF("gaorufeng");objectOutputStream.flush();// 接收并打印服务器传输的数据System.out.println(objectInputStream.readUTF());} finally {if (socket!=null) socket.close();if (objectOutputStream!=null) objectOutputStream.close();if (objectInputStream!=null) objectInputStream.close();}}
}
BIO阻塞的两个地方:
1、服务端执行serverSocket.accept()方法后会进入阻塞,直到有客户端请求进来
2、服务器如果是单线程运行(一个线程处理多个客户端请求会进入阻塞),如果数据还没传输完毕,其它客户端socket是无法与服务端建立tcp连接的,虽然socket显示连接成功,但是tcp连接还没建立
BIO适合少量连接的使用场景
BIO多线程通信模型:

2、原生JDK网络编程NIO
面向缓冲的非阻塞IO
1)NIO的Reactor模式
BIO和NIO最大的区别就是线程阻塞和不阻塞,NIO就是基于Reactor模式实现的,所谓Reactor模式,就是往一个组件注册感兴趣的事件并监听,触发对应的事件进行处理,而不是阻塞

2)NIO三大核心组件
- Selector选择器:Java NIO的选择器允许一个单独的线程来监视多个输入通道,你可以注册多个通道使用一个选择器(Selectors),然后使用一个单独的线程来操作这个选择器,进而“选择”通道:这些通道里已经有可以处理的输入,或者选择已准备写入的通道。这种选择机制,使得一个单独的线程很容易来管理多个通道(应用程序将向 Selector 对象注册需要它关注的 Channel,以及具体的某一个 Channel会对哪些 IO 事件感兴趣。Selector 中也会维护一个“已经注册的Channel”的容器)。
- Channel管道:被建立的一个应用程序和操作系统交互事件、传递内容的渠道(注意是连接到操作系统)。那么既然是和操作系统进行内容的传递,那么说明应用程序可以通过通道读取数据,也可以通过通道向操作系统写数据,而且可以同时进行读写。
- buffer缓冲区:JDK NIO是面向缓冲的。Buffer就是这个缓冲,用于和 NIO 通道进行交互。 数据是从通道读入缓冲区,从缓冲区写入到通道中的。以写为例,应用程序都是将数据写入 缓冲,再通过通道把缓冲的数据发送出去,读也是一样,数据总是先从通道读到缓冲,应用程序再读缓冲的数据。
public class NioSelectorServer {public static void main(String[] args) throws IOException, InterruptedException {// 创建NIO ServerSocketChannelServerSocketChannel serverSocket = ServerSocketChannel.open();serverSocket.socket().bind(new InetSocketAddress(9000));// 设置ServerSocketChannel为非阻塞serverSocket.configureBlocking(false);// 打开Selector处理Channel,即创建epollSelector selector = Selector.open();// 把ServerSocketChannel注册到selector上,并且selector对客户端accept连接操作感兴趣serverSocket.register(selector, SelectionKey.OP_ACCEPT);System.out.println("服务启动成功");while (true) {// 阻塞等待需要处理的事件发生selector.select();// 获取selector中注册的全部事件的 SelectionKey 实例Set<SelectionKey> selectionKeys = selector.selectedKeys();Iterator<SelectionKey> iterator = selectionKeys.iterator();// 遍历SelectionKey对事件进行处理while (iterator.hasNext()) {SelectionKey key = iterator.next();// 如果是OP_ACCEPT事件,则进行连接获取和事件注册if (key.isAcceptable()) {ServerSocketChannel server = (ServerSocketChannel) key.channel();SocketChannel socketChannel = server.accept();socketChannel.configureBlocking(false);// 这里只注册了读事件,如果需要给客户端发送数据可以注册写事件socketChannel.register(selector, SelectionKey.OP_READ);System.out.println("客户端连接成功");} else if (key.isReadable()) { // 如果是OP_READ事件,则进行读取和打印SocketChannel socketChannel = (SocketChannel) key.channel();ByteBuffer byteBuffer = ByteBuffer.allocate(128);int len = socketChannel.read(byteBuffer);// 如果有数据,把数据打印出来if (len > 0) {System.out.println("接收到消息:" + new String(byteBuffer.array()));} else if (len == -1) { // 如果客户端断开连接,关闭SocketSystem.out.println("客户端断开连接");socketChannel.close();}}//从事件集合里删除本次处理的key,防止下次select重复处理iterator.remove();}}}
}
相关文章:
NIO和BIO编程
一、网络通信编程基本常识 1、什么是Socket? Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口,一般由操作系统提供。 2、短连接 短连接是指socket建立连接之后传输数据确定接收完后关闭连接 3、长连接 长连接是指建立so…...
嵌入式系统设计师考试笔记之操作系统基础复习笔记二
目录 3、任务管理 (1)嵌入式操作系统的任务管理可以分为 (2)进程 (3)线程 (4)任务 (5)任务的创建与中止 (6)任务的状态任务有三…...
读图数据库实战笔记01_初识图
1. 图论 1.1. 起源于莱昂哈德欧拉在1736年发表的一篇关于“哥尼斯堡七桥问题”的论文 1.2. 要解决这个问题,该图需要零个或两个具有奇数连接的节点 1.3. 任何满足这一条件的图都被称为欧拉图 1.4. 如果路径只访问每条边一次,则该图具有欧拉路径 1.5…...
K-Means和KNN
主要区别 从无序 —> 有序 从K-Means —> KNN KNN:监督学习,类别是已知的,对已知分类的数据进行训练和学习,找到不同类的特征,再对未分类的数据进行分类。K-Means:无监督学习,事先不知道…...
【Python】【Flask】flask_login的初始化
【背景】 想要更高效地用现有的Flask_login包来实现用户管理方面的常用功能会话管理等。不想再手搓了。 【要点】 首先引入flask_login from flask_login import LoginManager, login_user, login_required, logout_user,current_user然后进行app级别的设置和初始化 login…...
Spring Cloud之API网关(Gateway)
目录 API网关 好处 解决方案 Gateway 简介 特征 核心概念 Route(路由) Predicate(断言) Filter(过滤器) 工作流程 Route(路由) 路由配置方式 1.yml配置文件路由 2.bean进行配置 3.动态路由 动态路由 Predicate(断言) 特点 常见断言 示例 Filter(过滤器) …...
nodejs+vue 电子书阅读系统
本文首先介绍了电子书阅读系统的发展背景与发展现状,然后遵循软件常规开发流程,首先针对系统选取适用的语言和开发平台,随着网络技术的不断发展,多媒体技术应用渐渐的出现在教育领域中,电子书阅读已经成为社会的一个热…...
百度文心一言4.0抢先体验教程!
🍁 展望:关注我, AI学习之旅上,我与您一同成长! 一、 引言 想快速体验文心一言4.0,但又觉得技术难度太高?别担心,我来手把手教你! 🚀 10月17日,文心一言4.0…...
单目3D目标检测 方法综述——直接回归方法、基于深度信息方法、基于点云信息方法
本文综合整理单目3D目标检测的方法模型,包括:基于几何约束的直接回归方法,基于深度信息的方法,基于点云信息的方法。万字长文,慢慢阅读~ 直接回归方法 涉及到模型包括:MonoCon、MonoDLE、MonoFlex、CUPNet…...
oracle,CLOB转XML内存不足,ORA-27163: out of memory ORA-06512: at “SYS.XMLTYPE“,
通过kettle采集数据时,表输入的组件,查询报错。 ORA-27163: out of memory ORA-06512: at “SYS.XMLTYPE”, line 272 ORA-06512: at line 1 通过 ALTER SESSION SET EVENTS ‘31156 trace name context forever, level 0x400’; 修改会话配置 或直接修改…...
PHP与mysql数据库交互
PHP与mysql数据库交互 文章目录 PHP与mysql数据库交互方法速查建立与Mysql链接捕获连接错误SQL语句的执行SQL 错误SQL语句执行结果集对象方法速查 案例 方法速查 函数名 作用 mysqli_connect() 与MySQL 数据库建立连接。 mysqli_close() 关闭与MYSQL 数据库建…...
【广州华锐视点】VR飞行员驾驶模拟实训系统
VR飞行员驾驶模拟实训系统是一种基于虚拟现实技术的航空装备仿真测试技术,可以用于飞行员、乘务员和机务人员的训练。该系统可以模拟真实的飞行环境,包括天气、地形、飞机性能等,使被试者能够在虚拟环境中进行飞行操作,从而提高其…...
太烂的牌也要打完只为自己也不是为了其他什么原因。
day17_io02 1.上课代码敲一遍 2.读取一个文件,这个文件中有随机的一些数字字符,统计这些数字有几个偶数,几个奇数,并且追加写入到该文件末尾。 例如: a.txt文件: 3241256364789629090126581212515 奇数&…...
SDL窗口创建以及简单显示(1)
项目创建步骤 1. 使用Qt Creator创建一个C项目 2. 将SDL库文件放到源文件目录下 在项目pro文件中添加库文件 win32{INCLUDEPATH $$PWD/SDL2-2.0.10/includeLIBS $$PWD/SDL2-2.0.10/lib/x86/SDL2.lib } 使用SDL创建一个窗口 #include <stdio.h>#include <SDL.h>…...
【Html】交通灯问题
效果 实现方式 计时器:setTimeout或setInterval来计时。setInterval和 setTimeout 在某些情况下可能会出现计时不准确的情况。这通常是由于JavaScript的事件循环机制和其他代码执行所需的时间造成的。 问询:通过getCurrentLight将每个状态的持续时间设置…...
用IntelliJ远程打断点调试
前提当然是本地和远程部署的代码一样。 记录下步骤: 1,用token登录kuboard,找到目标容器的IP: 2, 用上一步找到的IP等信息创建Remote JVM Debug: 3,打断点,wkb说要把断点此属性改为线程。我试了下似乎…...
Spring-Bean的生命周期概述
Bean的生命周期概述 入门使用的Spring代码: ClassPathXmlApplicationContext context new ClassPathXmlApplicationContext("spring.xml"); UserService userService (UserService) context.getBean("userService"); userService.test(); …...
SENet 学习
ILSVRC 是一个比赛,全称是ImageNet Large-Scale Visual Recognition Challenge,平常说的ImageNet比赛指的是这个比赛。 使用的数据集是ImageNet数据集的一个子集,一般说的ImageNet(数据集)实际上指的是ImageNet的这个子…...
目前和未来的缓存构建
说起来可能有点反直觉,有时候不运行反而可以帮助我们加快速度,这正是网络浏览器运行的指导原则。不必在页面上加载所有内容,缓存的元素已经存在,不需要每次访问网站或网页时都重新加载。页面加载速度越快,浏览器的工作…...
aws亚马逊云免费账号代充值!!!什么是 AWS Lambda?
AWS Lambda 是一项计算服务,可使您无需预配置或管理服务器即可运行代码。 Lambda 在可用性高的计算基础设施上运行您的代码,执行计算资源的所有管理工作,其中包括服务器和操作系统维护、容量调配和弹性伸缩和记录。使用 Lambda,您…...
【磁盘】每天掌握一个Linux命令 - iostat
目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat(I/O Statistics)是Linux系统下用于监视系统输入输出设备和CPU使…...
MVC 数据库
MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...
【C语言练习】080. 使用C语言实现简单的数据库操作
080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...
MySQL用户和授权
开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务: test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...
在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?
uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件,用于在原生应用中加载 HTML 页面: 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...
智能AI电话机器人系统的识别能力现状与发展水平
一、引言 随着人工智能技术的飞速发展,AI电话机器人系统已经从简单的自动应答工具演变为具备复杂交互能力的智能助手。这类系统结合了语音识别、自然语言处理、情感计算和机器学习等多项前沿技术,在客户服务、营销推广、信息查询等领域发挥着越来越重要…...
LOOI机器人的技术实现解析:从手势识别到边缘检测
LOOI机器人作为一款创新的AI硬件产品,通过将智能手机转变为具有情感交互能力的桌面机器人,展示了前沿AI技术与传统硬件设计的完美结合。作为AI与玩具领域的专家,我将全面解析LOOI的技术实现架构,特别是其手势识别、物体识别和环境…...
渗透实战PortSwigger靶场:lab13存储型DOM XSS详解
进来是需要留言的,先用做简单的 html 标签测试 发现面的</h1>不见了 数据包中找到了一个loadCommentsWithVulnerableEscapeHtml.js 他是把用户输入的<>进行 html 编码,输入的<>当成字符串处理回显到页面中,看来只是把用户输…...
消防一体化安全管控平台:构建消防“一张图”和APP统一管理
在城市的某个角落,一场突如其来的火灾打破了平静。熊熊烈火迅速蔓延,滚滚浓烟弥漫开来,周围群众的生命财产安全受到严重威胁。就在这千钧一发之际,消防救援队伍迅速行动,而豪越科技消防一体化安全管控平台构建的消防“…...
ubuntu22.04 安装docker 和docker-compose
首先你要确保没有docker环境或者使用命令删掉docker sudo apt-get remove docker docker-engine docker.io containerd runc安装docker 更新软件环境 sudo apt update sudo apt upgrade下载docker依赖和GPG 密钥 # 依赖 apt-get install ca-certificates curl gnupg lsb-rel…...
