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,您…...
NodeList 对象
NodeList 对象 概述 NodeList 对象是 DOM(文档对象模型)中的一种数据结构,它代表了包含在一个父节点内的所有元素节点的一个集合。NodeList 对象常用于处理文档中的多个元素,是 JavaScript 在操作 DOM 时的一个重要工具。 特点 1. 长度属性 NodeList 对象具有一个 len…...
Python 实战:数据归一化 4 种核心方法对比 + 代码实现(机器学习必看)
在机器学习、深度学习的数据预处理中,数据归一化是绕不开的关键步骤。不同特征往往量纲不同(比如年龄 18-60、收入 1000-100000),直接训练模型会导致:梯度下降收敛慢、难以最优解距离类算法(KNN、K-Means、…...
谷歌SEO网站收录秘籍:如何用AI工具去创作高质量文章
2026年谷歌SEO算法趋势与AI工具实操逻辑,我将从 “技术基建 - 关键词挖掘 - AI创作优化 - 收录加速” 四大核心环节,拆解 AI 创作高质量收录文章的完整方法论,所有技巧均基于最新实测数据与工具实操经验。一、前提认知:AI 谷歌 S…...
OpenCore Legacy Patcher完全指南:突破硬件限制让旧Mac焕发新生
OpenCore Legacy Patcher完全指南:突破硬件限制让旧Mac焕发新生 【免费下载链接】OpenCore-Legacy-Patcher Experience macOS just like before 项目地址: https://gitcode.com/GitHub_Trending/op/OpenCore-Legacy-Patcher OpenCore Legacy Patcher是一款强…...
覆盖更远、组网更稳:基于 EFR32BG21 的智能家居与物联网 BLE Mesh 无线模块方案
智能家居与物联网设备越来越多,但真正决定体验上限的往往不是“有没有连上网”,而是信号能不能到、掉线后能不能自愈、多设备同时在线是否还稳定。单靠点对点蓝牙,很容易在隔墙、远距离、多节点场景里碰到瓶颈;而把低功耗蓝牙与 M…...
软件开发常见骗局有哪些?
虚假高薪招聘陷阱以“零经验高薪入职”“包就业”为噱头,要求求职者付费培训。实际培训内容质量低下,承诺的就业机会无法兑现,甚至诱导贷款支付培训费用。外包项目诈骗谎称有高额预算项目外包,要求开发者支付“保证金”或“预付款…...
linux source命令作用及使用场景
source 是 Linux/Unix 系统中的一个内置 Shell 命令,主要用于在当前 Shell 环境中执行脚本文件(而非启动子 Shell),从而直接影响当前环境(如变量、函数、别名等)。以下是其详细作用及使用场景: …...
凌晨裁员3万人,史上最大裁员潮来了!
作者 | 文韬报道 | 环球电商“我们决定取消您的岗位,今天是您的最后一个工作日。”不少员工醒来才发现,岗位没了,系统权限也快没了,今天就是最后一个工作日。过去大家总觉得,只有快撑不住的公司,才会用这种…...
EVA-01应用实战:5个场景教你用Qwen2.5-VL处理工作学习中的图片难题
EVA-01应用实战:5个场景教你用Qwen2.5-VL处理工作学习中的图片难题 1. 引言:当视觉理解遇上机甲美学 想象一下,你正在处理一份满是手写笔记的文档照片,或者需要快速理解一张复杂的数据图表。传统方法可能需要你手动输入文字、反…...
快速启动Tensorboard并解决本地端口访问问题的实战指南
1. Tensorboard快速启动指南 Tensorboard是TensorFlow生态中不可或缺的可视化工具,它能直观展示模型训练过程中的损失曲线、准确率、计算图等重要信息。但很多新手在第一次使用时,常常卡在启动后无法访问的环节。这里分享我调试过上百个模型总结出的启动…...
