Node.js+Express+Nodemon+Socket.IO构建Web实时通信
陈拓 2023/11/23-2023/11/27
1. 简介
- Websocket
WebSocket是一种在单个TCP连接上提供全双工通讯的协议。特别适合需要持续数据交换的服务,例如在线游戏、实时交易系统等。
- Websocket与Ajax之间的区别
Ajax代表异步JavaScript和XML。它被用作一组Web开发技术,使Web开发变得更加容易。它可以说是客户端的Web技术,用于创建异步Web应用程序。使用 Ajax,Web应用程序可以从给定服务器检索数据,而无需更改当前行为。
它们在创建网页时都很有用。当需要传统的请求-响应时,可以使用Ajax,当涉及实时通信并且需要快速结果时,可以使用Websockets。
- socket.io.js
官方网址:
https://socket.io/zh-CN

Socket.IO是一个基于事件驱动的实时通信JavaScript库,可以在客户端和服务器之间建立持久连接,实现低延迟,双向,跨平台、跨浏览器的实时通信。
Socket.IO是构建在WebSocket协议之上的。
但要注意,Socket.IO不是WebSocket实现。尽管Socket.IO确实使用WebSocket进行传输,但它为每个数据包添加了额外的元数据,因此WebSocket客户端将无法成功连接到Socket.IO服务器,同样,Socket.IO客户端也将无法连接到普通WebSocket服务器。
2. 安装Node.js LTS
在安装Socket.IO之前要先安装Node.js。
2.1 Node.js简介
Javascript是浏览器客户端脚本语言,代码可以直接嵌在HTML文件中或在HTML中引用外部以.js结尾的文件。
Node.js是一个可以在后端服务器上运行Javascript脚本语言的环境。Node.js用C++编写,是一个Javascript命令解释器,是跨平台的。
类比Python运行环境可以让Python命令或脚本语言程序在计算机上运行。
npm的全称是 Node Package Manager,是随同 NodeJS 一起安装的包管理和分发工具,它可以很方便的让前端开发者下载、安装、上传以及管理已经安装的包。
下面的操作我们在Win10系统上使用ssh操作Linux服务器,操作说明请参考:
《Win10命令窗口的SSH和SFTP操作》
https://blog.csdn.net/chentuo2000/article/details/119918637?spm=1001.2014.3001.5501
2.2 安装Node.js
- 查看最新版本
https://nodejs.org/en/download/

- 安装最新版本的Node.js LTS(包含npm)
先根据最新版本号执行命令:
curl -sL https://deb.nodesource.com/setup_20.x | sudo -E bash -
……
根据提示执行命令:sudo apt-get install -y nodejs

- 安装成功测试
![]()
![]()
在安装好node.js后可以在服务器的命令行进行以下操作进行进一步的测试。
- 可以在命令行输入node以交互方式运行Javascript代码
例如:

- 也可以node *.js的方式运行js文件
例如,将上面的3行代码写到一个test.js文件中
nano server.js

运行test.js:
![]()
- 建立Web服务器
我们用Javascript写一个Web服务器程序,在node.js上运行,就启动了一个Web服务,下面详细说明。
2.3 node.js建立web服务器
- 创建一个项目目录并进入它
mkdir inode
cd inode

- 初始化package
凡是使用npm管理的项目,都需要初始化一个package.json文件。
可以使用以下命令来初始化一个包(package就是应用程序):
npm init
当执行这个命令时,它会通过问答的形式来一步步进行设置。如果不需要修改默认的配置,直接一路回车即可。如果想跳过向导,快速生成一个package.json 文件,可以执行以下命令:
npm init --yes
其中,--yes可以简写为-y。这时生成的package.json文件的配置项就是npm的默认配置。当然这个默认配置也是可以更改的,可以通过类似下面这样的形式来修改 npm 的默认配置:
npm config set init.author.name YOUR_NAME
npm config set init.author.email YOUR_EMAIL
当执行以上命令之后,之后再执行npm init命令时,package.json的作者姓名和邮箱都会初始化为我们设定的值。

npm init命令将引导您输入各种有关您的应用程序的详细信息,例如名称,版本号,描述等。最后,您将获得一个包含在package.json文件中的配置文件。
生成的package.json文件:

可以直接编辑修改package.json文件。
- 创建服务器文件server.js并开始编写代码
touch server.js
nano server.js

写代码:
const http = require('http');const hostname = '192.168.137.9';
const port = 3000;const server = http.createServer((req, res) => {res.statusCode = 200;res.setHeader('Content-Type', 'text/plain');res.end('Hello World');
});server.listen(port, hostname, () => {console.log(`Server running at http://${hostname}:${port}/`);
});
在此代码示例中,我们创建了一个HTTP服务器,并在该服务器上监听3000端口。当服务器收到请求时,它将在浏览器中返回“Hello World”
- 启动服务器
node server.js

- 从浏览器访问服务器
2.4 结束node.js进程,停止服务
在cmd窗口Ctrl+C退出node

用这种方式退出不会保留HTTP服务进程,再次启动服务时不会提示端口被占用。
3. 使用Express
Express官网:http://www.expressjs.com
Express是基于Node.js平台的快速、开放、极简的Web开发框架。
为什么要使用Express?
当我们创建服务器时,由Node.js提供的http内置模块使用复杂,开发效率低。
Express对node.js的http模块做了封装,通过Express可以使用更少的代码来实现Node.js的功能,可以极大提高开发效率。
3.1 安装Express
sudo npm install express --save
--save参数表示自动修改package.json文件,自动添加依赖项。

express安装到了~/node_modules目录下。
3.2 使用express访问html静态页面
在上一节的例子中,对于浏览器的请求响应是写在server.js中的,对于复杂的网页我们写成html文件,下面用一个简单的例子演示。
- 在前面的inode目录下面再创建目录public
mkdir public
html、css、js、图片等静态资源都放在public目录下面。
- 在目录public中创建一个页面index.html
nano public/index.html
![]()

<html>
<p>Hello World!</p>
</html>
- 写服务器js文件
服务器的js文件还放在inode目录下面。
nano server_express.js
![]()
写代码:
// server_express.js
const express = require('express');
const path = require('path');
const app = express();app.use(express.static(path.join(__dirname, 'public')));const hostname = '192.168.137.9';
const port = 3000;app.listen(port, hostname, () => {console.log(`Server running at http://${hostname}:${port}/`);
});
- 启动服务器
node server_express.js

- 从浏览器访问服务器

4. 使用Nodemon
为什么要使用Nodemon?
在编写调试Node.js项目的时候,如果修改了项目的代码,需要手动结束node.js进程,停止服务,然后再重新启动,非常繁琐。
Nodemon基于Node.js开发,是一个监视文件变化并自动重启应用程序的工具,能够监听项目中文件的变动,当代码被修改后,nodemon会帮我们自动重启项目,极大方便了开发和调试。
4.1 安装Nodemon
sudo npm install -g nodemon
-g表示全局范围安装。
-g: 为 --global 的缩写,表示安装到全局目录里
Node.js的全局目录是用来存放全局安装的模块或者包的,全局安装指的是针对整个系统,而不是针对某一个项目,安装的包或者模块可以在系统中的任何地方引用。

![]()
nodemon安装到了全局目录/usr/bin/nodemon下。
4.2 使用Nodemon
- 启动应用程序
nodemon app.js
这会启动你的应用程序,并监视相关文件的变化。
- 指定监视文件的扩展名
nodemon --ext js,html,css app.js
通过--ext参数,你可以指定Nodemon监视的文件扩展名。
- 忽略特定文件或文件夹
nodemon --ignore public/ app.js
使用--ignore参数可以忽略指定的文件或文件夹。
- 监视子文件夹
nodemon --recursive app.js
通过--recursive参数,Nodemon可以监视子文件夹中的文件变化。
- 在控制台输出详细日志
nodemon --verbose app.js
使用--verbose参数可以打印出更多的日志信息。
5. 在服务器端安装使用Socket.IO
5.1 我的服务器系统架构和操作系统版本
5.2 安装Socket.IO
- 安装socket.io库
sudo npm install socket.io

socket.io安装在node_modules目录。
5.3 官方入门示例:一个简单的聊天程序
https://socket.io/zh-CN/get-started/chat
在本指南中,我们将创建一个基本的聊天应用程序。它几乎不需要具备Node.JS或Socket.IO的基本知识,因此它非常适合所有知识级别的用户。
5.3.1 介绍
使用LAMP(PHP)等流行的web应用程序栈编写聊天应用程序通常非常困难。它包括轮询服务器以获取更改,跟踪时间戳,而且速度比应该的慢得多。
传统上,套接字(Sockets)是大多数实时聊天系统的解决方案,它提供了客户端和服务器之间的双向通信通道。
这意味着服务器可以向客户端推送消息。每当你写聊天消息时,服务器会得到它,并将消息推送给所有与服务器连接的客户端。
5.3.2 web框架
该示例使用Node.JS的web框架express。
第一个目标是建立一个简单的HTML网页,提供一个表单和一个消息列表。我们将使用Node.JS的web框架express来构建示例代码。
- 我们先建一个空目录chat-example。
mkdir chat-example
- cd chat-example
- 创建一个package.json清单文件来描述我们的项目
nano package.json

{"name": "socket-chat-example","version": "0.0.1","description": "my first socket.io app","dependencies": {}
}
注意:
“name”属性必须是唯一的,不能使用像“socket.io”或“express”这样的值。
- 创建一个index.js文件来设置我们的应用程序。
nano index.js
![]()

const express = require('express');
const app = express();
const http = require('http');
const server = http.createServer(app);app.get('/', (req, res) => {res.send('<h1>Hello world</h1>');
});server.listen(3000, '192.168.137.9', () => {console.log('listening on 192.168.137.9:3000');
});
说明:
Express将应用程序初始化为可以提供给HTTP服务器的函数处理程序(如第4行所示)。
我们定义了一个路由处理程序,当我们访问我们的网站主页时会调用它。
我们让http服务器在端口3000上侦听。
192.168.137.9是我的内网服务器ccde的ip地址。
- 运行index.js
可以用命令node index.js运行index.js
![]()
如果代码有改变,需要重新启动Web服务。
也可以用前面安装的nodemon来运行index.js,这样可以在修改代码时自动重启Web服务。
用Ctrl + c结束index.js的运行,重新用nodemon启动它。
nodemon index.js

同样,可以用Ctrl + C结束用nodemon运行的index.js。
- 在浏览器上访问192.168.137.9:3000
我使用谷歌浏览器Chrome。
http://192.168.137.9:3000/
5.3.3 使用HTML
到目前为止,在index.js中,我们调用res.send并向其传递一个HTML字符串。如果我们把整个应用程序的HTML都放在那里,我们的代码看起来会非常混乱,所以我们将创建一个index.HTML文件并在index.js使用它。
在index.js中让我们重构路由处理程序,改为使用sendFile。
因为我们用nodemon运行的index.js,要先写html文件,再改index.js。
- 写一个index.html文件
目前index.js还在nodemon控制下运行,我们重新打开一个CMD窗口来写index.html。
![]()
<!DOCTYPE html>
<html><head><title>Socket.IO chat</title><style>body { margin: 0; padding-bottom: 3rem; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; }#form { background: rgba(0, 0, 0, 0.15); padding: 0.25rem; position: fixed; bottom: 0; left: 0; right: 0; display: flex; height: 3rem; box-sizing: border-box; backdrop-filter: blur(10px); }#input { border: none; padding: 0 1rem; flex-grow: 1; border-radius: 2rem; margin: 0.25rem; }#input:focus { outline: none; }#form > button { background: #333; border: none; padding: 0 1rem; margin: 0.25rem; border-radius: 3px; outline: none; color: #fff; }#messages { list-style-type: none; margin: 0; padding: 0; }#messages > li { padding: 0.5rem 1rem; }#messages > li:nth-child(odd) { background: #efefef; }</style></head><body><ul id="messages"></ul><form id="form" action=""><input id="input" autocomplete="off" /><button>Send</button></form></body>
</html>
- 修改index.js
nano index.js
![]()
修改代码中粗体显示的部分:
const express = require('express');
const app = express();
const http = require('http');
const server = http.createServer(app);app.get('/', (req, res) => {res.sendFile(__dirname + '/index.html');
});server.listen(3000, '192.168.137.9', () => {console.log('listening on 192.168.137.9:3000');
});
- 在浏览器上访问192.168.137.9:3000
因为我们使用了nodemon运行index.js,所以不用重启index.js。

在第一个CMD窗口可以看到nodemon为我们重启了Web服务。
5.3.4 集成Socket.IO
- Socket.IO由两部分组成
1) 与Node.JS集成(或装载在Node.JS上)的HTTP服务器 socket.io。
2) 一个加载在浏览器端的socket.io-client客户端库
在开发过程中,socket.io会自动为我们的客户端提供服务,因此目前我们只需要在服务端安装一个socket.io模块。这个模块我们在前面已经安装好了。
- 在index.html中的</body>标签之前添加以下代码段
nano index.html

<script src="/socket.io/socket.io.js"></script>
<script>var socket = io();
</script>
这就是加载socket.io-client所需的全部内容,它暴露了一个io全局变量(以及端点GET/socket.io/socket.io.js)socket,然后进行连接。
请注意,当我调用io()时,我没有指定任何URL,因为它默认尝试连接到为页面提供服务的主机。
- 编辑index.js来添加socket.io
为例响应index.html的socket.io连接请求,我们需要修改index.js。
nano index.js

const express = require('express');
const app = express();
const http = require('http');
const server = http.createServer(app);
const { Server } = require("socket.io");
const io = new Server(server);app.get('/', (req, res) => {res.sendFile(__dirname + '/index.html');
});io.on('connection', (socket) => {console.log('a user connected');
});server.listen(3000, '192.168.137.9', () => {console.log('listening on 192.168.137.9:3000');
});
请注意,我通过传递服务器(HTTP服务器)对象来初始化socket.io的一个新实例。然后,我监听传入套接字socket的连接事件,并将其日志记录输出到控制台。
- 在浏览器上查看
nodemon已经为我们重启了Web服务,直接刷新浏览器就可以。
点击3次浏览器刷新,在服务端的控制台上会看到客户端的连接消息。

- 断开连接事件disconnect event
每个套接字socket还会触发一个特殊的断开连接事件disconnect event
io.on('connection', (socket) => {console.log('a user connected');socket.on('disconnect', () => {console.log('user disconnected');});
});

5.3.5 触发事件
- Socket.IO背后的主要思想
IO指您可以发送和接收任何您需要的事件,以及任何您想要的数据。任何可以编码为JSON的对象都可以,二进制数据也受支持。
让我们这样做,当用户输入消息时,服务器会将其作为聊天消息事件 chat message获取。
- 修改index.html中的脚本部分
<script src="/socket.io/socket.io.js"></script>
<script>var socket = io();var form = document.getElementById('form');var input = document.getElementById('input');form.addEventListener('submit', function(e) {e.preventDefault();if (input.value) {socket.emit('chat message', input.value);input.value = '';}});
</script>
- 在index.js中,我们打印出聊天消息事件
chat message
io.on('connection', (socket) => {socket.on('chat message', (msg) => {console.log('message: ' + msg);});
});
- 在浏览器上输入消息,并发送
先刷新一下页面,再发消息。

- 在服务器控制台查看
5.3.6 广播
我们的下一个目标是将事件从服务器发送给其他用户。
为了向每个人发送一个事件,Socket.IO给了我们IO.emit()方法。
io.emit('some event', { someProperty: 'some value', otherProperty: 'other value' }); // This will emit the event to all connected sockets
如果你想向除某个socket(比如发送者)之外的所有人发送消息,我们使用广播标志broadcast :
io.on('connection', (socket) => {socket.broadcast.emit('hi');
});
在本例中,为了简单起见,我们将把消息发送给每个人,包括发送者,见下面的index.js。
在客户端,当我们捕获到一个chat message事件时,我们会将其包含在页面中。客户端JavaScript代码的所有代码如下:
- 修改index.html
<script src="/socket.io/socket.io.js"></script>
<script>var socket = io();var messages = document.getElementById('messages');var form = document.getElementById('form');var input = document.getElementById('input');form.addEventListener('submit', function(e) {e.preventDefault();if (input.value) {socket.emit('chat message', input.value);input.value = '';}});socket.on('chat message', function(msg) {var item = document.createElement('li');item.textContent = msg;messages.appendChild(item);window.scrollTo(0, document.body.scrollHeight);});
</script>
- 修改index.js
在代码
io.on('connection', (socket) => {socket.on('chat message', (msg) => {console.log('message: ' + msg);});
});
之后添加:
io.on('connection', (socket) => {socket.on('chat message', (msg) => {io.emit('chat message', msg);});
});
- 在浏览器上输入消息

点击Send,浏览器显示:

在同一个网络的计算机浏览器连接192.168.137.9:3000后都可以接收到这个消息,当然手机也可以。
- 服务器控制台上显示

这就完成了我们的聊天应用程序,大约只需要20行代码!
5.3.7 作业
以下是一些改进应用程序的想法:
- 当有人连接或断开连接时,向连接的用户广播消息。
- 添加对昵称的支持。
- 不要向发送消息的用户发送相同的消息。相反,只要用户按enter键,就直接附加消息。
5.3.8 获取完整的chat-example示例
- 获取示例
cd ~/inode/
git clone https://github.com/socketio/chat-example.git


- 运行测试
node index.js

为node.js安装sqlite3模块:
sudo npm install sqlite3 --save
再启动Web服务:
node index.js

再打开一个网页,连接http://192.168.137.9:3001
两个网页互相发送消息:

有条件可以用多台电脑进行测试。
附:卸载Node.js
如果第一次装node.js没装好,需要
卸掉重装,下面是卸载过程。
参考《如何卸载干净nodejs》
https://www.php.cn/faq/547208.html
- 获取Node.js的安装位置:
whereis node
which node

根据输出结果,删除所有Node.js文件和目录。
- 卸载Node.js
sudo apt-get remove --purge nodejs
- 删除Node.js二进制文件
sudo rm -rf /usr/local/lib/node* /usr/local/bin/node* /usr/local/include/node* /usr/local/share/man/man1/node*
- 删除NPM
sudo apt-get remove npm
sudo apt-get autoremove npm
- 删除节点许可证
Node.js安装包内置MIT许可证,您可以在安装目录中找到它。
sudo find / -name LICENSE
sudo rm -r /usr/local/n
sudo rm -r /usr/local/lib/dtrace
- 删除Node.js包存储
sudo rm -rf /usr/local/lib/node_modules
- 删除Node.js模块
sudo rm -rf /usr/local/include/node /usr/local/lib/node_modules /usr/local/share/man/man1/node* /usr/local/bin/node
参考文档
- WebSocket之socket.io的基本使用
https://blog.csdn.net/G_ing/article/details/129651543 - Web Sockets vs Ajax
https://www.educba.com/web-sockets-vs-ajax/ - Nodemon详解,超全!!!——打造高效的Node.js开发环境
https://blog.csdn.net/m0_72410588/article/details/131911655
相关文章:
Node.js+Express+Nodemon+Socket.IO构建Web实时通信
陈拓 2023/11/23-2023/11/27 1. 简介 Websocket WebSocket是一种在单个TCP连接上提供全双工通讯的协议。特别适合需要持续数据交换的服务,例如在线游戏、实时交易系统等。 Websocket与Ajax之间的区别 Ajax代表异步JavaScript和XML。它被用作一组Web开发技术&…...
广州华锐互动:AR可视化展示昆虫让教学过程更直观生动
随着科技的不断发展,AR(增强现实)技术已经逐渐走进我们的生活。通过AR技术,我们可以将虚拟的信息叠加到现实世界中,让现实世界变得更加丰富多彩。在这篇文章中,我们将以昆虫为主题,探讨AR增强现…...
.NET开源的处理分布式事务的解决方案
前言 在分布式系统中,由于各个系统服务之间的独立性和网络通信的不确定性,要确保跨系统的事务操作的最终一致性是一项重大的挑战。今天给大家推荐一个.NET开源的处理分布式事务的解决方案基于 .NET Standard 的 C# 库:CAP。 CAP项目介绍 CA…...
如何隐藏选择选项值并用新值替换2个选项?
要隐藏选择选项值并用新值替换2个选项,可以使用JavaScript来实现。 首先,使用JavaScript获取两个选项的值,然后将这两个值设置为新的值,最后将这两个选项的可见性设置为false,以隐藏它们。 例如: <se…...
[读论文][跑代码]BK-SDM: A Lightweight, Fast, and Cheap Version of Stable Diffusion
github: GitHub - Nota-NetsPresso/BK-SDM: A Compressed Stable Diffusion for Efficient Text-to-Image Generation [ICCV23 Demo] [ICML23 Workshop] ICML 2023 Workshop on ES-FoMo 简化方式 蒸馏方式(训练Task蒸馏outKD-FeatKD) 训练数据集 评测指标…...
机器学习的复习笔记1
机器学习是一种人工智能的分支,它通过让计算机从数据中学习规律和模式,从而实现对未知数据的预测和决策。根据不同的学习方法和任务,机器学习可以分为以下几种类型: 监督学习:在监督学习中,计算机会被提供一…...
【Spring Boot】如何集成Swagger
Swagger简单介绍 Swagger是一个规范和完整的框架,用于生成、描述、调用和可视化RESTful风格的Web服务。功能主要包含以下几点: 可以使前后端分离开发更加方便,有利于团队协作接口文档可以在线自动生成,有利于降低后端开发人员编写…...
优化-查询数据接口太慢
有一个查询接口,主业务表有几万多条数据,没超过十万,由于没有使用分页,所以每次查询都要返回大几万的数据,然后问题是前端页面查询数据显示数据要转很久。 压缩响应体大小 我发现查询的时间是1秒多,但是浏…...
c++ 谓词
1. 一元谓词 #include <iostream> #include<vector> #include<algorithm>using namespace std;class CreaterFive{ public:bool operator()(int val){return val>5;} };int main() {vector<int> vec;for(int i0; i<10; i){vec.push_back(i);}ve…...
一篇总结 Linux 系统启动的几个汇编指令
学习 Linux 系统启动流程,必须熟悉几个汇编指令,总结给大家。 这里不是最全的,只列出一些最常用的汇编指令。 一.数据处理指令 1.数据传送指令 【MOV指令】 把一个寄存器的值(立即数)赋给另一个寄存器,或者将一个…...
python技术栈之单元测试中mock的使用
什么是mock? mock测试就是在测试过程中,对于某些不容易构造或者不容易获取的对象,用一个虚拟的对象来创建以便测试的测试方法。 mock的作用 特别是开发过程中上下游未完成的工序导致当前无法测试,需要虚拟某些特定对象以便测试…...
LeetCode(37)矩阵置零【矩阵】【中等】
目录 1.题目2.答案3.提交结果截图 链接: 73. 矩阵置零 1.题目 给定一个 m x n 的矩阵,如果一个元素为 0 ,则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 示例 1: 输入:matrix [[1,1,1],[1,0,1],[1,1,1]…...
[Python入门系列之十一]在windows上安装OpenCV
1-安装OpenCV 如果是python3.7–python3.9(已测试),直接安装即可 注:conda需要先激活虚拟环境后再安装 pip install opencv-python如果安装速度慢,使用下面的指令: pip install opencv-python -i https://pypi.tuna.tsinghua.e…...
论文阅读——SEEM
arxiv: 分割模型向比较灵活的分割的趋势的转变:封闭到开放,通用到特定、one-shot到交互式。From closed-set to open-vocabulary segmentation,From generic to referring segmentation,From one-shot to interactive segmentati…...
Python入门06布尔值
目录 1 什么是布尔值2 怎么生成布尔值3 在控制程序中使用布尔值4 数据过滤、排序和其他高级操作总结 1 什么是布尔值 首先我们要学习一下布尔值的定义,布尔值是一种数据类型,它只有两个可能的值:True(真)或 False&…...
js查询详情接口控制执行时间的命令
在JavaScript中,可以使用console.time()和console.timeEnd()来控制执行时间的命令。 console.time()用于开始计时,可以指定一个标识符作为参数,用于标识计时器。 console.time(query); // 执行查询操作 console.timeEnd(query); 执行上述代…...
Linux系统iptables
目录 一. 防火墙简介 1. 防火墙定义 2. 防火墙分类 ①. 网络层防火墙 ②. 应用层防火墙 二. iptables 1. iptables定义 2. iptables组成 ①. 规则表 ②. 规则链 3. iptables格式 ①. 管理选项 ②. 匹配条件 ③. 控制类型 四. 案例说明 1. 查看规则表 2. 增加新…...
每日一题 1410. HTML 实体解析器(中等,模拟)
模拟,没什么好说的 class Solution:def entityParser(self, text: str) -> str:entityMap {": ",': "",>: >,<: <,⁄: /,&: &,}i 0n len(text)res []while i < n:isEntity Falseif …...
Docker Swarm总结+service创建和部署、overlay网络以及Raft算法(2/5)
博主介绍:Java领域优质创作者,博客之星城市赛道TOP20、专注于前端流行技术框架、Java后端技术领域、项目实战运维以及GIS地理信息领域。 🍅文末获取源码下载地址🍅 👇🏻 精彩专栏推荐订阅👇🏻…...
对抗产品团队中的认知偏误:给产品经理的专家建议
今天的产品经理面临着独特的挑战。他们不仅需要设计和构建创新功能,还必须了解这些功能将如何为客户带来价值并推进关键业务目标。如果不加以控制,认知偏差可能会导致您构建的内容与客户想要的内容或业务需求之间不一致。本文将详细阐述产品经理可以避免…...
基于FPGA的PID算法学习———实现PID比例控制算法
基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容:参考网站: PID算法控制 PID即:Proportional(比例)、Integral(积分&…...
中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试
作者:Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位:中南大学地球科学与信息物理学院论文标题:BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接:https://arxiv.…...
【机器视觉】单目测距——运动结构恢复
ps:图是随便找的,为了凑个封面 前言 在前面对光流法进行进一步改进,希望将2D光流推广至3D场景流时,发现2D转3D过程中存在尺度歧义问题,需要补全摄像头拍摄图像中缺失的深度信息,否则解空间不收敛…...
tree 树组件大数据卡顿问题优化
问题背景 项目中有用到树组件用来做文件目录,但是由于这个树组件的节点越来越多,导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多,导致的浏览器卡顿,这里很明显就需要用到虚拟列表的技术&…...
【JVM面试篇】高频八股汇总——类加载和类加载器
目录 1. 讲一下类加载过程? 2. Java创建对象的过程? 3. 对象的生命周期? 4. 类加载器有哪些? 5. 双亲委派模型的作用(好处)? 6. 讲一下类的加载和双亲委派原则? 7. 双亲委派模…...
CSS | transition 和 transform的用处和区别
省流总结: transform用于变换/变形,transition是动画控制器 transform 用来对元素进行变形,常见的操作如下,它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...
【 java 虚拟机知识 第一篇 】
目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...
C语言中提供的第三方库之哈希表实现
一. 简介 前面一篇文章简单学习了C语言中第三方库(uthash库)提供对哈希表的操作,文章如下: C语言中提供的第三方库uthash常用接口-CSDN博客 本文简单学习一下第三方库 uthash库对哈希表的操作。 二. uthash库哈希表操作示例 u…...
快速排序算法改进:随机快排-荷兰国旗划分详解
随机快速排序-荷兰国旗划分算法详解 一、基础知识回顾1.1 快速排序简介1.2 荷兰国旗问题 二、随机快排 - 荷兰国旗划分原理2.1 随机化枢轴选择2.2 荷兰国旗划分过程2.3 结合随机快排与荷兰国旗划分 三、代码实现3.1 Python实现3.2 Java实现3.3 C实现 四、性能分析4.1 时间复杂度…...
uni-app学习笔记三十五--扩展组件的安装和使用
由于内置组件不能满足日常开发需要,uniapp官方也提供了众多的扩展组件供我们使用。由于不是内置组件,需要安装才能使用。 一、安装扩展插件 安装方法: 1.访问uniapp官方文档组件部分:组件使用的入门教程 | uni-app官网 点击左侧…...





