【小沐学前端】Node.js实现基于Protobuf协议的WebSocket通信
文章目录
- 1、简介
- 1.1 Node
- 1.2 WebSocket
- 1.3 Protobuf
- 2、安装
- 2.1 Node
- 2.2 WebSocket
- 2.2.1 nodejs-websocket
- 2.2.2 ws
- 2.3 Protobuf
- 3、代码测试
- 3.1 例子1:websocket(html)
- 3.1.1 客户端:yxy_wsclient1.html
- 3.1.2 客户端:yxy_wsclient1_2.html
- 3.2 例子2:websocket(js)
- 3.2.1 服务端:yxy_wsserver2.js
- 3.2.2 客户端:yxy_wsclient2.js
- 3.3 例子3:websocket(js+html)
- 3.3.1 服务端:yxy_wsserver3.js
- 3.3.2 客户端:yxy_wsclient3.html
- 3.3.3 客户端:yxy_wsclient3_2.html
- 3.3.4 客户端:yxy_wsclient3_3.html
- 3.4 例子4:websocket(js+proto)
- 3.4.1 服务端:yxy_wsserver4.js
- 3.4.2 客户端:yxy_wsclient4.js
- 3.5 例子5:websocket(js+express)
- 3.5.1 服务端:yxy_wsserver5.js
- 3.5.2 客户端:yxy_wsclient5.html
- 结语
1、简介
1.1 Node
Node.js发布于2009年5月,由Ryan Dahl开发,是一个基于Chrome V8引擎的JavaScript运行环境,使用了一个事件驱动、非阻塞式I/O模型,让JavaScript 运行在服务端的开发平台,它让JavaScript成为与PHP、Python、Perl、Ruby等服务端语言平起平坐的脚本语言。
简单的说 Node.js 就是运行在服务端的 JavaScript。
Node.js 是一个基于 Chrome JavaScript 运行时建立的一个平台。
Node.js 是一个事件驱动 I/O 服务端 JavaScript 环境,基于 Google 的 V8 引擎,V8 引擎执行 Javascript 的速度非常快,性能非常好。
1.2 WebSocket
https://developer.mozilla.org/zh-CN/docs/Web/API/WebSocket
WebSocket是一个长连接,客户端可以给服务端发送消息,服务端也可以给客户端发送消息,这便是全双工通信。
WebSocket是html5规范中的一个部分,它借鉴了socket这种思想,为web应用程序客户端和服务端之间(注意是客户端服务端)提供了一种全双工通信机制。同时,它又是一种新的应用层协议,WebSocket协议是为了提供web应用程序和服务端全双工通信而专门制定的一种应用层协议,通常它表示为:ws://echo.websocket.org/?encoding=text HTTP/1.1。通俗的讲,WebSocket 是一种新的网络通信协议,现在浏览器端很多高级功能都需要用到它。
WebSockets 是一种先进的技术。它可以在用户的浏览器和服务器之间打开交互式通信会话。使用此 API,你可以向服务器发送消息并接收事件驱动的响应,而无需通过轮询服务器的方式以获得响应。
WebSocket 是一种网络传输协议,可在单个 TCP 连接上进行全双工通信,位于 OSI 模型的应用层。WebSocket 协议在 2011 年由 IETF 标准化为 RFC 6455,后由 RFC 7936 补充规范。
WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就可以创建持久性的连接,并进行双向数据传输。
1.3 Protobuf
Google Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,或者说序列化。它很适合做数据存储或 RPC 数据交换格式。可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。
https://github.com/protocolbuffers/protobuf
Protobuf (Protocol Buffers) 是谷歌开发的一款无关平台,无关语言,可扩展,轻量级高效的序列化结构的数据格式,用于将自定义数据结构序列化成字节流,和将字节流反序列化为数据结构。所以很适合做数据存储和为不同语言,不同应用之间互相通信的数据交换格式,只要实现相同的协议格式,即后缀为proto文件被编译成不同的语言版本,加入各自的项目中,这样不同的语言可以解析其它语言通过Protobuf序列化的数据。
2、安装
2.1 Node
https://nodejs.org/en
2.2 WebSocket
下面给出了WebSocket数据帧的统一格式。
0 1 2 30 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-------+-+-------------+-------------------------------+
|F|R|R|R| opcode|M| Payload len | Extended payload length |
|I|S|S|S| (4) |A| (7) | (16/64) |
|N|V|V|V| |S| | (if payload len==126/127) |
| |1|2|3| |K| | |
+-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
| Extended payload length continued, if payload len == 127 |
+ - - - - - - - - - - - - - - - +-------------------------------+
| |Masking-key, if MASK set to 1 |
+-------------------------------+-------------------------------+
| Masking-key (continued) | Payload Data |
+-------------------------------- - - - - - - - - - - - - - - - +
: Payload Data continued ... :
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
| Payload Data continued ... |
+---------------------------------------------------------------+
2.2.1 nodejs-websocket
https://www.npmjs.com/package/nodejs-websocket
用于 websocket 服务器和客户端的 nodejs 模块
安装库nodejs-websocket:
npm i nodejs-websocket
查看库nodejs-websocket 的当前本地安装版本:
npm ls nodejs-websocket -g
- 入门示例
var ws = require("nodejs-websocket")// Scream server example: "hi" -> "HI!!!"
var server = ws.createServer(function (conn) {console.log("New connection")conn.on("text", function (str) {console.log("Received "+str)conn.sendText(str.toUpperCase()+"!!!")})conn.on("close", function (code, reason) {console.log("Connection closed")})
}).listen(8001)
2.2.2 ws
https://www.npmjs.com/package/ws
ws: a Node.js WebSocket library
ws 是一个简单易用、速度快、经过全面测试的 WebSocket 客户端和 服务器实现。
或者安装库ws:
npm i ws
查看库ws的当前本地安装版本:
npm ls ws -g
2.3 Protobuf
https://github.com/protobufjs/protobuf.js/
Protocol Buffers for JavaScript (& TypeScript).
安装库protobufjs :
npm install protobufjs [--save --save-prefix=~]
npm install protobufjs-cli [--save --save-prefix=~]
查看库protobufjs 的当前本地安装版本:
npm ls protobufjs -g
3、代码测试
3.1 例子1:websocket(html)
3.1.1 客户端:yxy_wsclient1.html
- yxy_wsclient1.html
var ws = new WebSocket("wss://echo.websocket.org");ws.onopen = function(evt) { console.log("Connection open ..."); ws.send("Hello WebSockets!");
};ws.onmessage = function(evt) {console.log( "Received Message: " + evt.data);ws.close();
};ws.onclose = function(evt) {console.log("Connection closed.");
};
3.1.2 客户端:yxy_wsclient1_2.html
- yxy_wsclient1.html
// Create WebSocket connection.
const socket = new WebSocket("ws://localhost:8080");// Connection opened
socket.addEventListener("open", function (event) {socket.send("Hello Server!");
});// Listen for messages
socket.addEventListener("message", function (event) {console.log("Message from server ", event.data);
});
3.2 例子2:websocket(js)
3.2.1 服务端:yxy_wsserver2.js
const WebSocket = require('ws');//引入模块const wss = new WebSocket.Server({ port: 8080 });//创建一个WebSocketServer的实例,监听端口8080wss.on('connection', function connection(ws) {ws.on('message', function incoming(message) {console.log('received: %s', message);ws.send('Hi Client');});//当收到消息时,在控制台打印出来,并回复一条信息});
3.2.2 客户端:yxy_wsclient2.js
const WebSocket = require('ws');const ws = new WebSocket('ws://localhost:8080');ws.on('open', function open() {ws.send('Hi Server');
});//在连接创建完成后发送一条信息ws.on('message', function incoming(data) {console.log(data);
});//当收到消息时,在控制台打印出来
3.3 例子3:websocket(js+html)
3.3.1 服务端:yxy_wsserver3.js
- yxy_wsserver3.js
var ws = require("nodejs-websocket")
var PORT = 3000var server = ws.createServer(function (conn) {console.log("New connection")conn.on("text", function (str) {console.log("Received "+str)conn.sendText(str.toUpperCase()+"!!!")})conn.on("close", function (code, reason) {console.log("Connection closed")})conn.on("error",function(err){console.log('handler error')console.log(err)})
}).listen(PORT)console.log('websocket server listening on port ' + PORT)
- 运行结果如下:
3.3.2 客户端:yxy_wsclient3.html
- yxy_wsclient3.html
<html>
<head><meta charset="utf-8"/><title>websocket</title>
</head>
<body><h1>Echo test</h1><input id="sendTxt" type="text"/><button id="sendBtn">发送</button><div id="recv"></div><script type="text/javascript">// var websocket = new WebSocket("ws://echo.websocket.org/");var websocket = new WebSocket("ws://127.0.0.1:3000");websocket.onopen = function(){console.log('websocket open');document.getElementById('recv').innerHTML = 'Connected';}websocket.onclose = function(){console.log('websocket close');}websocket.onmessage = function(event){console.log(event.data);document.getElementById('recv').innerHTML = event.data;}document.getElementById('sendBtn').onclick = function(){var txt = document.getElementById('sendTxt').value;websocket.send(txt);}</script>
</body>
- 运行结果如下:
3.3.3 客户端:yxy_wsclient3_2.html
- yxy_wsclient3_2.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>WenSocket</title><style>div{width: 200px;height: 200px;border:1px solid;margin-top: 5px;}</style>
</head>
<body><input type="text" placeholder="请输入内容"><button>提交</button><div></div><script>const input = document.querySelector('input')const button = document.querySelector('button')const div = document.querySelector('div')//创建WebSocket实例// const socket = new WebSocket("ws://echo.websocket.org")const socket = new WebSocket("ws://127.0.0.1:3000")//监听服务是否链接socket.addEventListener('open',()=>{div.innerHTML = "服务链接成功"})//button触发点击事件,将input框中的内容发送至websocket//查看websocket是否接收到数据:chrome F12打开控制台》Network》WS》echo.websocket.org》messagesbutton.addEventListener('click',()=>{const value = input.valuesocket.send(value)})// 将接收到的数据插入到div中socket.addEventListener('message',(e)=>{console.log(e)div.innerHTML = e.data})</script>
</body>
</html>
- 运行结果如下:
3.3.4 客户端:yxy_wsclient3_3.html
- yxy_wsclient3_3.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>WebSocket</title><style></style>
</head>
<body><input type="text" placeholder="请输入内容"><button>提交</button><div></div><script>const input = document.querySelector('input')const button = document.querySelector('button')const div = document.querySelector('div')const socket = new WebSocket('ws://127.0.0.1:3000')socket.addEventListener('open',()=>{div.innerText = "欢迎来到聊天室"})button.addEventListener('click',()=>{const value = input.valuesocket.send(value)input.value = ''})socket.addEventListener('message',(e)=>{//div.innerText = e.data //这种方法会覆盖原先的数据const dv = document.createElement('div')dv.innerText = e.datadiv.appendChild(dv)})</script>
</body>
</html>
3.4 例子4:websocket(js+proto)
WebSocket是HTML5新增的协议,它的目的是在浏览器和服务器之间建立一个不受限的双向通信的通道,比如说,服务器可以在任意时刻发送消息给浏览器。任何一方都可以主动发消息给对方。
HTTP协议是一个请求-响应协议,请求必须先由浏览器发给服务器,服务器才能响应这个请求,再把数据发送给浏览器。换句话说,浏览器不主动请求,服务器是没法主动发数据给浏览器的。
WebSocket并不是全新的协议,而是利用了HTTP协议来建立连接。
安装ws库:
npm i ws
- user.proto
syntax = "proto3";
package yxy;message Login {required string name = 1;required string pwd = 2;
}
message Address{string province = 1;string city = 2;string country = 3;
}
3.4.1 服务端:yxy_wsserver4.js
- yxy_wsserver4.js
const protobuf = require("protobufjs");
const PORT = 3000;
const HOST = '127.0.0.1';protobuf.load("./user.proto", (err, root) => {if (err) throw err;const LoginMessage = root.lookupType("yxy.Login");const WebSocket = require('ws')const WebSocketServer = WebSocket.Server;const wss =new WebSocketServer({port:PORT})//如果有WebSocket请求接入,wss对象可以响应connection事件来处理这个WebSocket:wss.on('connection',function(ws){ //在connection事件中,回调函数会传入一个WebSocket的实例,表示这个WebSocket连接。console.log(`[SERVER] connection()`);ws.on('message',function(message){console.log(`[SERVER] Received:${message}`);// 解码数据 const payload = LoginMessage.decode(message);// 在这里处理消息console.log(payload);// 编码响应 const responseData = LoginMessage.encode({name: "杨小羊",pwd: "111111"}).finish();const msg = responseData.toString();ws.send(`ECHO:${msg}` ,(err)=>{if(err){console.log(`[SERVER] error:${err}`);}})})})
});
- 运行结果如下:
3.4.2 客户端:yxy_wsclient4.js
- yxy_wsclient4.js
const protobuf = require("protobufjs");
const PORT = 3000;
const HOST = '127.0.0.1';protobuf.load("./user.proto", (err, root) => {if (err) throw err;const LoginMessage = root.lookupType("yxy.Login");const WebSocket = require('ws')let ws = new WebSocket('ws://localhost:3000');// 打开WebSocket连接后立刻发送一条消息:ws.on('open', function () {console.log(`[CLIENT] open()`);//每隔一秒向服务器发送消息,以便后面每隔一秒收到消息setInterval(function(){// 编码数据 const data = LoginMessage.encode({name: "爱看书的小沐",pwd: "222222"}).finish();// 将数据写到连接 ws.send(data);console.log(`[CLIENT] Send: ${data}`);},1000)});// 响应收到的消息:ws.on('message', function (message) {console.log(`[CLIENT] Received: ${message}`);const loginResponse = LoginMessage.decode(message);console.log(loginResponse);})
});
- 运行结果如下:
3.5 例子5:websocket(js+express)
3.5.1 服务端:yxy_wsserver5.js
- yxy_wsserver5.js
var app = require('express')();
var server = require('http').Server(app);
var WebSocket = require('ws');var wss = new WebSocket.Server({port: 8080
});wss.on('connection', function connection(ws) {console.log('server: receive connection.');ws.on('message', function incoming(message) {console.log('server: received: %s', message);});ws.send('world');
});app.get('/', function (req, res) {res.sendfile(__dirname + '/index.html');
});app.listen(3000);
3.5.2 客户端:yxy_wsclient5.html
- yxy_wsclient5.html
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>WebSocket</title><style></style>
</head><body><script>var ws = new WebSocket('ws://localhost:8080');ws.onopen = function () {console.log('ws onopen');ws.send('from client: hello');};ws.onmessage = function (e) {console.log('ws onmessage');console.log('from server: ' + e.data);};
</script></body>
</html>
结语
如果您觉得该方法或代码有一点点用处,可以给作者点个赞,或打赏杯咖啡;
╮( ̄▽ ̄)╭
如果您感觉方法或代码不咋地
//(ㄒoㄒ)//,就在评论处留言,作者继续改进;
o_O???
如果您需要相关功能的代码定制化开发,可以留言私信作者;
(✿◡‿◡)
感谢各位大佬童鞋们的支持!
( ´ ▽´ )ノ ( ´ ▽´)っ!!!
相关文章:

【小沐学前端】Node.js实现基于Protobuf协议的WebSocket通信
文章目录 1、简介1.1 Node1.2 WebSocket1.3 Protobuf 2、安装2.1 Node2.2 WebSocket2.2.1 nodejs-websocket2.2.2 ws 2.3 Protobuf 3、代码测试3.1 例子1:websocket(html)3.1.1 客户端:yxy_wsclient1.html3.1.2 客户端:…...

MySQL学习笔记24
MySQL的物理备份: xtrabackup备份介绍: xtrabackup优缺点: 优点: 1、备份过程快速、可靠(因为是物理备份);直接拷贝物理文件。 2、支持增量备份,更为灵活; 3、备份…...

objective-c 基础学习
目录 第一节:OC 介绍 第二节:Fundation 框架 第三节:NSLog 相对于print 的增强 第四节:NSString 第五节:oc新增数据类型 第六节: 类和对象 类的方法的声明与实现 第七节:类…...

【精彩回顾】 用sCrypt在Bitcoin上构建智能合约
2023年3月24日,sCrypt在英国Exeter大学举办了关于智能合约的大学讲学。sCrypt首席执行官刘晓晖做了题为“用sCrypt在Bitcoin上构建智能合约”的演讲,并与到场的老师、学生进行了深入交流、互动。这次课程着重讲解了 BSV 智能合约的基础概念,以…...
Kotlin 使用泛型
在 Kotlin 中,我们可以使用泛型(Generics)来编写具有通用性的代码,以增强代码的可重用性和类型安全性。通过使用泛型,我们可以在不指定具体类型的情况下编写适用于多种类型的函数和类。 以下是 Kotlin 中使用泛型的几…...

深度学习 二:COVID 19 Cases Prediction (Regression)
Deep Learning 1. 回归算法思路2. 代码2.1 基础操作2.2 定义相关函数2.3.1 定义图像绘制函数2.3.2 数据集加载及预处理2.3.3 构造数据加载器2.3.4 构建前馈神经网络(Feedforward Neural Network)模型2.3.5 神经网络的训练过程2.3.6 模型评估2.3.7 模型测…...
UG\NX二次开发 信息窗口的4种输出方式 NXOpen::ListingWindow::DeviceType
文章作者:里海 来源网站:《里海NX二次开发3000例专栏》 简介 UG\NX二次开发 信息窗口的4种输出方式 NXOpen::ListingWindow::DeviceType 信息窗口的输出类型 enum NXOpen::ListingWindow::DeviceType 枚举值描述 DeviceTypeWindow0输出将写入“信息”窗口DeviceTypeFile1输出…...
mavn打包时如何把外部依赖加进去?
一、添加依赖: <dependency><groupId>com.dm</groupId><artifactId>DmJdbcDriver</artifactId><version>18</version><scope>system</scope><systemPath>${project.basedir}/lib/DmJdbcDriver18.jar</systemP…...

爬虫代理请求转换selenium添加带有账密的socks5代理
爬虫代理请求转换selenium添加带有账密的socks5代理。 一、安装三方库 二、使用方法 1、在cmd命令行输入: 2、给selenium添加代理 最近因为工作需要,需要selenium添加带有账密的socks5代理,贴出一个可用的方法。 把带有账密的socks5代理&am…...
Redis 如何实现数据不丢失的?
Redis 实现数据不丢失的关键在于使用了多种持久化机制,以确保数据在内存和磁盘之间的持久性。以下是 Redis 实现数据不丢失的主要方法: 快照(Snapshot)持久化: Redis 使用快照持久化来定期将内存中的数据写入磁盘。快照是一个数据库状态的副本,包含了所有键和与其相关联的…...
[高等数学]同济版高等数学【第七版】上下册教材+习题全解PDF
laiyuan 「高等数学 第7版 同济大学」 https://www.aliyundrive.com/s/5fpFJb3asYk 提取码: 61ao 通过百度网盘分享的文件:同济版高数教材及… 链接:https://pan.baidu.com/s/1gyy-GMGjwguAjYijrpC8RA?pwdyhnr 提取码:yhnr 高等数学相关: The Ca…...
【面试题精讲】Java超过long类型的数据如何表示
有的时候博客内容会有变动,首发博客是最新的,其他博客地址可能会未同步,认准https://blog.zysicyj.top 首发博客地址[1] 面试题手册[2] 系列文章地址[3] 在 Java 中,如果需要表示超过 long 类型范围的数据,可以使用 BigInteger 类…...
Shapiro-Wilk正态性检验(Shapiro和Wilk于1965年提出)
Shapiro-Wilk正态性检验是一种用于确定数据集是否服从正态分布的统计方法。它基于Shapiro和Wilk于1965年提出的检验统计量。以下是其基本原理和用途: 基本原理: 零假设(Null Hypothesis):Shapiro-Wilk检验的零假设是数…...

debian设置允许ssh连接
解决新debian系统安装后不能通过ssh连接的问题。 默认情况下,Debian系统不开启SSH远程登录,需要手动安装SSH软件包并设置开机启动。 > 设置允许root登录传送门:debian设置允许root登录 首先检查/etc/ssh/sshd_config文件是否存在。 注意…...

【C语言经典100例题-66】(用指针解决)输入3个数a,b,c,按大小顺序输出。
代码: #include<stdio.h> #define _CRT_SECURE_NO_WARNINGS 1//VS编译器使用scanf函数时会报错,所以添加宏定义 swap(p1, p2) int* p1, * p2; {int p;p *p1;*p1 *p2;*p2 p; } int main() {int n1, n2, n3;int* pointer1, * pointer2, * point…...

【STM32 CubeMX】移植u8g2(一次成功)
文章目录 前言一、下载u8g2源文件二、复制和更改文件2.1 复制文件2.2 修改文件u8g2_d_setup文件u8g2_d_memory 三、编写oled.c和oled.h文件3.1 CubeMX配置I2C3.2 编写文件oled.holed.c 四、测试代码main函数测试代码 总结 前言 在本文中,我们将介绍如何在STM32上成…...

华为云智能化组装式交付方案 ——金融级PaaS业务洞察及Web3实践的卓越贡献
伴随信息技术与金融业务加速的融合,企业应用服务平台(PaaS)已从幕后走向台前,成为推动行业数字化转型的关键力量。此背景下,华为云PaaS智能化组装式交付方案闪耀全场,在近日结束的华为全联接大会 2023上倍受…...
Halcon Image相关算子(二)
(1) dyn_threshold(OrigImage, ThresholdImage : RegionDynThresh : Offset, LightDark : ) 功能:从输入图像中选择像素满足阈值条件的那些区域。 图形输入参数:OrigImage:原始图像; 图形输入参数:ThresholdImage&a…...
Rust 多线程编程
一个进程一定有一个主线程,主线程之外创建出来的线程称为子线程 多线程编程,其实就是在主线程之外创建子线程,让子线程和主线程并发运行,完成各自的任务。 Rust语言支持多线程编程。 Rust语言标准库中的 std::thread 模块用于多线…...

JavaScript高阶班之ES6 → ES11(八)
JavaScript高阶班之ES6 → ES11 1、ES6新特性1.1、let 关键字1.2、const关键字1.3、变量的解构赋值1.3.1、数组的解构赋值1.3.2、对象的解构赋值 1.4、模板字符串1.5、简化对象写法1.6、箭头函数1.7、函数参数默认值1.8、rest参数1.9、spread扩展运算符1.9.1、数组合并1.9.2、数…...

MongoDB学习和应用(高效的非关系型数据库)
一丶 MongoDB简介 对于社交类软件的功能,我们需要对它的功能特点进行分析: 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具: mysql:关系型数据库&am…...

Day131 | 灵神 | 回溯算法 | 子集型 子集
Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣(LeetCode) 思路: 笔者写过很多次这道题了,不想写题解了,大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...
java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别
UnsatisfiedLinkError 在对接硬件设备中,我们会遇到使用 java 调用 dll文件 的情况,此时大概率出现UnsatisfiedLinkError链接错误,原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用,结果 dll 未实现 JNI 协…...
Robots.txt 文件
什么是robots.txt? robots.txt 是一个位于网站根目录下的文本文件(如:https://example.com/robots.txt),它用于指导网络爬虫(如搜索引擎的蜘蛛程序)如何抓取该网站的内容。这个文件遵循 Robots…...
Pinocchio 库详解及其在足式机器人上的应用
Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库,专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性,并提供了一个通用的框架&…...
React---day11
14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store: 我们在使用异步的时候理应是要使用中间件的,但是configureStore 已经自动集成了 redux-thunk,注意action里面要返回函数 import { configureS…...

NXP S32K146 T-Box 携手 SD NAND(贴片式TF卡):驱动汽车智能革新的黄金组合
在汽车智能化的汹涌浪潮中,车辆不再仅仅是传统的交通工具,而是逐步演变为高度智能的移动终端。这一转变的核心支撑,来自于车内关键技术的深度融合与协同创新。车载远程信息处理盒(T-Box)方案:NXP S32K146 与…...

【VLNs篇】07:NavRL—在动态环境中学习安全飞行
项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战,克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...

RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill
视觉语言模型(Vision-Language Models, VLMs),为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展,机器人仍难以胜任复杂的长时程任务(如家具装配),主要受限于人…...

STM32HAL库USART源代码解析及应用
STM32HAL库USART源代码解析 前言STM32CubeIDE配置串口USART和UART的选择使用模式参数设置GPIO配置DMA配置中断配置硬件流控制使能生成代码解析和使用方法串口初始化__UART_HandleTypeDef结构体浅析HAL库代码实际使用方法使用轮询方式发送使用轮询方式接收使用中断方式发送使用中…...