当前位置: 首页 > news >正文

如何使用websocket

如何使用websocket

之前看到过一个面试题:吃饭点餐的小程序里,同一桌的用户点餐菜单如何做到的实时同步?
答案就是:使用websocket使数据变动时服务端实时推送消息给其他用户。
最近在我们自己的项目中我也遇到了类似问题:后端需要调用第三方接口然后异步得到结果,前端却不知道具体的回调时间,只能反复轮询,后来找了找资料,想要达到服务端主动推送消息,也许需要使用websocket。
 

参考:
websocket 学习–简单使用,nodejs搭建websocket服务器
一文吃透 WebSocket
比第一个文章更加深入地实现:NodeJS 落地 WebSocket 实践
主参考(必看)
 

学习前的疑惑:

  1. 服务端广播消息时如何具体推送到相关用户?
  2. 代码书写中针对websocket的网络协议有没有什么不安全的行为,如何避免传输中信息泄露。
  3. 长连接涉及的断联和重传行为如何解决

1、什么是websocket

webSocket是一种网络应用层协议,它是基于TCP连接上进行全双工通信的协议,在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接, 并进行双向数据传输,也就是说可以达到服务端主动向客户端推送数据的效果。

WebSocket连接的过程是:

websocket首先通过HTTP协议把TCP连接好,然后通过Upgrade字段进行协议转化,收到服务器的101 Switching Protocols应答后,后续的TCP消息就通过websocket协议解析。

首先,WebSocket需要一个握手过程,在这里它利用了HTTP本身协议升级的特性。经过3次握手后,服务器和客户端建立起TCP连接,然后一方发起一个http get请求,请求头里存放WebSocket支持的版本号等信息,如:Upgrade、Connection、WebSocket-Version等;

  • “Connection: Upgrade”,表示要求协议“升级”;
  • “Upgrade: websocket”,表示要“升级”成 WebSocket 协议。
  • Sec-WebSocket-Key:一个 Base64 编码的 16 字节随机数,作为简单的认证密钥;
  • Sec-WebSocket-Version:协议的版本号,当前必须是 13。
    然后,服务器收到客户端的握手请求后,就不会走普通的 HTTP 处理流程,而是构造一个特殊的“101 Switching Protocols”响应报文,通知客户端,接下来就不用 HTTP 了,全改用 WebSocket 协议通信。;
  • Sec-WebSocket-Accept:响应报文响应头,具体是把请求头里Sec-WebSocket-Key的值+某一个UUID,计算一番传给客户端,然后客户端验证后连接成功。
    最后,客户端收到连接成功的消息后,开始借助于TCP传输信道进行全双工通信。

2、简单的demo

服务器采用epress+ws简单构建。 然后node express-server.js启动。

// express-server.jsvar WebSocketServer = require('ws').Server;wss = new WebSocketServer({ port: 9999 });
wss.on('connection', function (ws) {console.log('client connected');ws.on('message', function (message) {console.log(message);ws.send('服务端接收到请求后,发送给客户端的数据' + message);});ws.on('close', () => {console.log('close');});
});

服务端使用react脚手架直接启一个,页面上将这个封装好的测试连接组件显示出来。

import { useRef, useState } from 'react';
import { Button } from 'antd';export default function Index() {const ws = useRef(null);const startWs = () => {if ('WebSocket' in window) {// 初始化一个 WebSocket 对象,参数指明urlws.current = new WebSocket('ws://localhost:9999');// WebSocket 连接时候触发ws.current.onopen = () => {// 使用 send() 方法发送数据ws.current.send('客户端发送的数据');console.log('数据发送中...');};/*** 接收服务端数据时触发* @param {[{type:string,number:number}]} evt.data* @param {string} evt.data.type a :a+1,b:b+1* @param {number} evt.data.number*/ws.current.onmessage = (evt) => {let received_msg = evt.data;console.log('数据已接收...', received_msg);};// 断开 web socket 连接成功触发事件ws.current.onclose = () => {// 关闭 websocketconsole.log('连接已关闭...');};} else {// 浏览器不支持 WebSocketconsole.log('您的浏览器不支持 WebSocket!');}};return (<><Button onClick={startWs}>测试WS连接</Button><div>{Object.keys(data).map((key) => (<h2>{key} : {data[key]}<br /></h2>))}</div></>);
}

是的,就上面两个代码,就能测试一个最简单的ws连接是什么样的。
打开浏览器的控制台 network也可以看到ws的传输报文。可以看到httpCode:101,而requestHeaders里包含几个升级到websocket的请求头,后续我们就可以利用这些特性进行连接的鉴权。

request
Sec-WebSocket-Key: 是随机的字符串,用于后续校验。
Origin: 请求源
Upgrade: websocket
Connection: Upgrade\

response
Sec-WebSocket-Accept: 用匹配寻找客户端连接的值,计算公式为toBase64(sha1( Sec-WebSocket-Key + 258EAFA5-E914-47DA-95CA-C5AB0DC85B11 ) )
这里的258EAFA5-E914-47DA-95CA-C5AB0DC85B11 为魔术字符串,为常量。

若计算不正确,或者没有返回该字段,则websocket连接不能建立成功。

3、连接的鉴权和安全行为

首先https的连接必须采用wss的连接方式(防止中间人)。
websocket本身是不支持http封装好的cookie 、headers等信息传递方式的,但是它在升级协议的那个请求还是http协议,因此我们可以手动实现一个类似cookie鉴权。
数据传输时的鉴权采取了基于信道建立时鉴权的方案,用户第一次认证后,回传给客户端一个类似token的令牌,用户在每一次使用websocket进行数据传输时,则需要回传这个token到服务端进行验证。


// 参考https://www.npmjs.com/package/ws
import { createServer } from 'http';
import { WebSocketServer } from 'ws';const server = createServer();
const wss = new WebSocketServer({ noServer: true });wss.on('connection', function connection(ws, request, client) {ws.on('message', function message(data) {console.log(`Received message ${data} from user ${client}`);});
});server.on('upgrade', function upgrade(request, socket, head) {// This function is not defined on purpose. Implement it with your own logic.authenticate(request, function next(err, client) {if (err || !client) {socket.write('HTTP/1.1 401 Unauthorized\r\n\r\n');socket.destroy();return;}wss.handleUpgrade(request, socket, head, function done(ws) {wss.emit('connection', ws, request, client);});});
});server.listen(8080);

4、开发过程中需要注意的心跳检测、断线重连机制。

长时间的保持连接是比较浪费网络资源的,因此对于很久没有响应的通道最好进行一个心跳检测,间隔一定时间发送一个心跳包,保持通道连接。
服务端发送心跳包可以直接使用封装好的方法:ws.ping('', false, true);
客服端这边发送心跳包需要自己定义一个定时器,假设保活时间为10分钟一次,收不到服务器返回的回应包就把连接挂了,其他的情况保持通道。

function heartCheck (ws) {const timeout = 10*60*1000; // 间隔10分钟发送一次。const serverTimeout = 5000; // 5秒内若还没有响应则关闭连接。let timer = null; // 心跳包的发送定时器。let serverTimer = null; // 服务器端响应定时器时间。// OnMessage接收消息则清除定时器。const resetServerTimer = () => {clearTimeout(resetTimer);};// 删除全部定时器(正常关闭链接或者没有收到心跳包)  const resetTimer = () => {clearTimeout(timer);clearTimeout(serverTimer);ws.close();};const start = () => {timer = setTimeout(()=>{//这里发送一个心跳,后端收到后,返回一个心跳消息,//onmessage拿到返回的心跳就说明连接正常ws.send("ping");serverTimer = (() => {resetTimer();},serverTimeout)},timeout)};return {resetServerTimer,resetTimer,start};
}


 

5、多个服务端的测试demo,如何推送消息到具体用户

// 服务端代码
var WebSocketServer = require('ws').Server;
const { createServer } =  require('http');wss = new WebSocketServer({ noServer:true });
const server = createServer();// 鉴权行为函数
const checkAuth = () => new Promise((res,rej)=>{res(true)
})let obj = {a:1,b:2}
let timer = null;// 定时器定时更新数据
function setImmediateFun (){timer = setImmediate(() => {obj = {a:obj.a+1,b:obj.b+1};},3000)          
}setImmediateFun();wss.on('connection', async function (ws,req,client) {// 检测协议升级时的鉴权 // 因为无法修改返回状态码以及返回token故采用ws.on("upgrade",(ws, req) => void)// if (headers['upgrade'] && headers['sec-websocket-key']) {//   // 请求用户服务身份验证//   const authorized = await checkAuth(headers.authToken);//   if(authorized){//     // 升级成功,生成一个token给客户端,状态码为101//   }else{//     // 连接失败,返回403//   }// }// open发送第一条消息ws.on('open', function (ws) {console.log("connect successfully");ws.send(JOSN.stringify(obj));});// 响应那边传来的数据,更新新数据ws.on('message', function (message) {ws.send(JSON.stringify(obj));wss.clients.forEach((client) => {// console.log(client)if (client.readyState === 1) {client.send(JSON.stringify(obj));}});});// 关闭连接ws.on('close', () => {console.log('close');clearInterval(timer)});
});server.on('upgrade', async function upgrade(request, socket, head) {if (await checkAuth(request.headers.authToken)) {// 升级成功,生成一个token给客户端,状态码为101wss.handleUpgrade(request, socket, head, function done(ws) {wss.emit('connection', ws, request);});}else{// 连接失败,返回403socket.write('HTTP/1.1 403 Unauthorized\r\n\r\n');socket.destroy();return;}
});server.listen(9999);
// 客户端代码
import { useRef, useState } from 'react';
import { Button } from 'antd';export default function Index() {const ws_current = useRef(null);let ws = ws_current.current;const [data, setData] = useState({ a: 0, b: 0 });const startWs = () => {if ('WebSocket' in window) {// 初始化一个 WebSocket 对象,参数指明urlws = new WebSocket('ws://localhost:9999');// WebSocket 连接时候触发ws.onopen = () => {console.log('连接成功');};/*** 接收服务端数据时触发* @param {[{type:string,number:number}]} evt.data* @param {string} evt.data.type a :a+1,b:b+1* @param {number} evt.data.number*/ws.onmessage = (evt) => {let received_msg = evt.data;received_msg = JSON.parse(received_msg);console.log(received_msg)setData(received_msg);console.log('数据已接收...', received_msg);};// 断开 web socket 连接成功触发事件ws.onclose = () => {// 关闭 websocketconsole.log('连接已关闭...');};} else {// 浏览器不支持 WebSocketconsole.log('您的浏览器不支持 WebSocket!');}};const sendMessage = () => {ws?.send('send message')}return (<><Button onClick={startWs}>测试WS连接</Button><Button onClick={sendMessage}>连接成功后发送信号获得响应数据</Button><div>{Object.keys(data).map((key) => (<h2>{key} : {data[key]}<br /></h2>))}</div></>);
}

相关文章:

如何使用websocket

如何使用websocket 之前看到过一个面试题&#xff1a;吃饭点餐的小程序里&#xff0c;同一桌的用户点餐菜单如何做到的实时同步&#xff1f; 答案就是&#xff1a;使用websocket使数据变动时服务端实时推送消息给其他用户。 最近在我们自己的项目中我也遇到了类似问题&#xf…...

C++ 调用lua 脚本

需求&#xff1a; 使用Qt/C 调用 lua 脚本 扩展原有功能。 步骤&#xff1a; 1&#xff0c;工程中引入 头文件&#xff0c;库文件。lua二进制下载地址&#xff08;Lua Binaries&#xff09; 2&#xff0c; 调用脚本内函数。 这里调用lua 脚本中的process函数&#xff0c;并…...

Centos 内存和硬盘占用情况以及top作用

目录 只查看内存使用情况&#xff1a; 内存使用排序取前5个&#xff1a; 硬盘占用情况 定位占用空间最大目录 top查看cpu及内存使用信息 前言-与正文无关 生活远不止眼前的苦劳与奔波&#xff0c;它还充满了无数值得我们去体验和珍惜的美好事物。在这个快节奏的世界中&…...

【数据结构】堆(创建,调整,插入,删除,运用)

目录 堆的概念&#xff1a; 堆的性质&#xff1a; 堆的存储方式&#xff1a; 堆的创建 &#xff1a; 堆的调整&#xff1a; 向下调整&#xff1a; 向上调整&#xff1a; 堆的创建&#xff1a; 建堆的时间复杂度&#xff1a; 向下调整&#xff1a; 向上调整&#xff…...

v-if 和v-for的联合规则及示例

第073个 查看专栏目录: VUE ------ element UI 专栏目标 在vue和element UI联合技术栈的操控下&#xff0c;本专栏提供行之有效的源代码示例和信息点介绍&#xff0c;做到灵活运用。 提供vue2的一些基本操作&#xff1a;安装、引用&#xff0c;模板使用&#xff0c;computed&a…...

各互联网企业测绘资质调研

公司子公司产品产品介绍资质获得资质时间阿里巴巴高德高德地图作为阿里的全资子公司&#xff0c;中国领先的数字地图内容、导航和位置服务解决方案提供商&#xff0c;互联网地图行业龙头&#xff0c;2021年4月高德实现全月平均日活跃用户数超过1亿的重要里程碑&#xff0c;稳居…...

C++自定义函数详解

个人主页&#xff1a;PingdiGuo_guo 收录专栏&#xff1a;C干货专栏 铁汁们新年好呀&#xff0c;今天我们来了解自定义函数。 文章目录 1.数学中的函数 2.什么是自定义函数 3.自定义函数如何使用&#xff1f; 4.值传递和引用传递&#xff08;形参和实参区分&#xff09; …...

flask+vue+python跨区通勤人员健康体检预约管理系统

跨区通勤人员健康管理系统设计的目的是为用户提供体检项目等功能。 与其它应用程序相比&#xff0c;跨区通勤人员健康的设计主要面向于跨区通勤人员&#xff0c;旨在为管理员和用户提供一个跨区通勤人员健康管理系统。用户可以通过系统及时查看体检预约等。 跨区通勤人员健康管…...

Spring Boot动态加载Jar包与动态配置技术探究

Spring Boot动态加载Jar包与动态配置技术探究 1. 引言 在当今快节奏的软件开发领域&#xff0c;高效的开发框架是保持竞争力的关键。Spring Boot作为一款快速开发框架&#xff0c;以其简化配置、内嵌Web服务器、强大的开发工具等特性&#xff0c;成为众多开发者的首选。其背后…...

Lua metatable metamethod

示例代码 《programming in lua》里有一个案例很详细&#xff0c;就是写一个集合类的table&#xff0c;其负责筛选出table中不重复的元素并组合成一个新的table。本人按照自己的方式默写了一次&#xff0c;结果发现大差不差&#xff0c;代码如下&#xff1a; Set {} --集合--…...

HCIA-HarmonyOS设备开发认证V2.0-3.2.轻量系统内核基础-任务管理

目录 一、任务管理1.1、任务状态1.2、任务基本概念1.3、任务管理使用说明1.4、任务开发流程1.5、任务管理接口 一、任务管理 从系统角度看&#xff0c;任务是竞争系统资源的最小运行单元。任务可以使用或等待CPU、使用内存空间等系统资源&#xff0c;并独立于其它任务运行。 O…...

中小型网络系统总体规划与设计方法

目录 1.基于网络的信息系统基本结构 2.网络需求调研与系统设计原则 3.网络用户调查 4.网络节点地理位置分布情况 5.网络需求详细分析 6.应用概要分析 7.网络工程设计总体目标与设计原则 8.网络结构与拓扑构型设计方法 9.核心层网络结构设计 10.接入核心路由器 11.汇聚…...

以管理员权限删除某文件夹

到开始菜单中找到—命令提示符—右击以管理员运行 使用&#xff1a;del /f /s /q “文件夹位置” 例&#xff1a;del /f /s /q "C:\Program Files (x86)\my_code\.git"...

JenkinsGitLab完成自动化构建部署

关于GitLab安装:GitLab安装-CSDN博客 Docker中安装GitLab:Docker下安装GitLab-CSDN博客 安装JenKins Jenkins官网:Jenkins 中文版:Jenkins 安装时候中文页面的war包下不来 在英文页面 记得装JDK8以上 JenKins使用java写的 运行JenKins需要JDK环境 我这里已经装好了 将下…...

JVM 性能调优 - 参数基础(2)

查看 JDK 版本 $ java -version java version "1.8.0_151" Java(TM) SE Runtime Environment (build 1.8.0_151-b12) Java HotSpot(TM) 64-Bit Server VM (build 25.151-b12, mixed mode) 查看 Java 帮助文档 $ java -help 用法: java [-options] class [args...] …...

大型软件编程实例分享,诊所门诊处方笺管理系统多台电脑同时使用的软件教程

大型软件编程实例分享&#xff0c;诊所门诊处方笺管理系统多台电脑同时使用的软件教程 一、前言 以下教程以 佳易王诊所门诊电子处方管理系统V17.2 为例说明 软件资源可以点击最下方官网卡片了解详情 软件左侧为导航栏 1、系统参数设置&#xff1a;可以设置打印等参数 2、…...

Java基于微信小程序的医院挂号系统

文章目录 1 简介2 技术栈3 系统目标3.2 系统功能需求分析3.2.1 功能需求分析 4 系统模块设计4.1 数据库模块设计 5 系统的实现5.1 微信小程序个人中心5.2 科**室内容查看的实现**5.3 预约挂号的实现5.4 后台管理界面实现5.5 医生预约管理5.6 医生信息管理 参考文献7 推荐阅读8 …...

你是在独立思考,还是在被洗脑?

你有过这样的经历吗&#xff1f; 老板走过来&#xff0c;急匆匆丢给你一句&#xff1a;帮我整理一下那个客户的资料&#xff0c;下午给我。你抬头&#xff0c;应道「好好好」。老板扬长而去。你转念一想&#xff1a; 等等&#xff0c;哪个客户&#xff1f;什么资料&#xff1f;…...

在django中集成markdown文本框

首先需要下载开源组件&#xff1a;http://editor.md.ipandao.com/&#xff0c;可能需要挂梯子。 百度网盘&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1D9o3P8EQDqSqfhAw10kYkw 提取码&#xff1a;eric 1.在html代码中生成一个div&#xff0c;ideditor <div c…...

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之Slider组件

鸿蒙&#xff08;HarmonyOS&#xff09;项目方舟框架&#xff08;ArkUI&#xff09;之Slider组件 一、操作环境 操作系统: Windows 10 专业版、IDE:DevEco Studio 3.1、SDK:HarmonyOS 3.1 二、Slider组件 滑动条组件&#xff0c;通常用于快速调节设置值&#xff0c;如音量调…...

django admin 自定义界面时丢失左侧导航 nav_sidebar

只显示了自定义模板的内容&#xff0c;左侧导航没有显示出来。 原因&#xff1a;context 漏掉了&#xff0c;要补上。 # 错误写法&#xff08;左侧导航不显示&#xff09;def changelist_view(self, request, extra_contextNone):form CsvImportForm()payload {"form&qu…...

JSP原理简述

JSP动态网页技术&#xff0c;可以定义html&#xff0c;css&#xff0c;js等静态内容&#xff0c;还可以定义java代码等动态内容。 注意导入坐标时&#xff0c;JSP的scope标签是provided&#xff0c;和servlet一样&#xff0c;否则会报错。 JSP本质上就是一个Servlet&#xff0c…...

C/C++ - 异常处理

目录 错误处理 异常处理 异常传播 异常规划 标准异常 自定异常 错误处理 在C语言中&#xff0c;错误通常通过函数的返回值来表示。 错误返回值 对于能返回特殊值&#xff08;如NULL或负值&#xff09;的函数&#xff0c;在调用时检查这些值来处理错误。 #include <st…...

十、项目开发总结报告(软件工程)

1&#xff0e;引言 1.1编写目的 1.2项目背景 1.3定义 1.4参考资料 2&#xff0e;开发结果 2.1产品 2.2主要功能及性能 2.3所用工时 2.4所用机时 2.5进度 2.6费用 3&#xff0e;评价 3.1生产率评价 3.2技术方案评价 3.3产品质量评价 4&#xff…...

在 VMware 虚拟机上安装 CentOS系统 完整(全图文)教程

一、前期准备&#xff1a; 1.安装VMware 虚拟机软件&#xff08;不在讲解&#xff0c;可自行去下载安装&#xff09;。官网&#xff1a;https://customerconnect.vmware.com/cn/downloads/details?downloadGroupWKST-PLAYER-1750&productId1377&rPId111471 2.下载iso…...

吉他学习:右手拨弦方法,右手拨弦训练 左手按弦方法

第六课 右手拨弦方法https://m.lizhiweike.com/lecture2/29362775 第七课 右手拨弦训练https://m.lizhiweike.com/lecture2/29362708...

【初识爬虫+requests模块】

爬虫又称网络蜘蛛、网络机器人。本质就是程序模拟人使用浏览器访问网站&#xff0c;并将需要的数据抓取下来。爬虫不仅能够使用在搜索引擎领域&#xff0c;在数据分析、商业领域都得到了大规模的应用。 URL 每一个URL指向一个资源&#xff0c;可以是一个html页面&#xff0c;一…...

微信小程序(三十八)滚动容器

注释很详细&#xff0c;直接上代码 上一篇 新增内容&#xff1a; 1.滚动触底事件 2.下拉刷新事件 源码&#xff1a; index.wxml <view class"Area"> <!-- scroll-y 垂直滚动refresher-enabled 允许刷新bindrefresherrefresh 绑定刷新作用函数bindscrollto…...

Python学习之路-Tornado基础:数据库

Python学习之路-Tornado基础:数据库 简介 与Django框架相比&#xff0c;Tornado没有自带ORM&#xff0c;对于数据库需要自己去适配。我们使用MySQL数据库。 在Tornado3.0版本以前提供tornado.database模块用来操作MySQL数据库&#xff0c;而从3.0版本开始&#xff0c;此模块…...

Golang的for循环变量和goroutine的陷阱,1.22版本的更新

先来看一段golang 1.22版本之前的for循环的代码 package mainimport "fmt"func main() {done : make(chan bool)values : []string{"chen", "hai", "feng"}for _, v : range values {fmt.Println("start")go func() {fmt.P…...

List 差集

文章目录 基本类型对象类型 基本类型 ListUtils.subtract 方法用于计算两个集合的差集&#xff0c;即返回 list1 中有但 list2 中没有的元素。 其中&#xff0c;list1 指向第一个集合&#xff0c;list2 指向第二个集合。该方法返回一个新的 List 对象&#xff0c;它包含所有在…...

ArcGIS的UTM与高斯-克吕格投影分带要点总结

UTM&#xff08;通用横轴墨卡托投影、等角横轴割椭圆柱投影&#xff09;投影分带投影要点&#xff1a; 1&#xff09;UTM投影采用6度分带 2&#xff09;可根据公式计算&#xff0c;带数&#xff08;经度整数位/6&#xff09;的整数部分31 3&#xff09;北半球地区&#xff0…...

华为第二批难题一:基于预训练AI模型的元件库生成

我的理解&#xff1a;华为的这个难道应该是想通过大模型技术&#xff0c;识别元件手册上的图文内容&#xff0c;与现有建库工具结合&#xff0c;有潜力按标准生成各种库模型。 正好&#xff0c;我们正在研究&#xff0c;利用知识图谱技术快速生成装配模型&#xff0c;其中也涉…...

Android AOSP源码研究之万事开头难----经验教训记录

文章目录 1.概述2.Android源下载1.配置环境变量2.安装curl3.下载repo并授权4.创建一个文件夹保存源码5.设置repo的地址并配置为清华源6.初始化仓库7.指定我们需要下载的源码分支并初始化 2.1 使用移动硬盘存放Android源码的坑2.2 解决方法 3.Android源码编译4.Android源烧录 1.…...

动态数据源

一、部署 1、导入依赖 <dependency><groupId>com.baomidou</groupId><artifactId>dynamic-datasource-spring-boot-starter</artifactId><version>3.1.0</version></dependency>2、编写yml 配置文件 spring:datasource:dyna…...

2024.1.29力扣每日一题——自由之路

2024.1.29 题目来源我的题解方法一 动态规划 题目来源 力扣每日一题&#xff1b;题序&#xff1a;514 我的题解 方法一 动态规划 定义 dp[i][j] 表示从前往后拼写出 key的第 i个字符&#xff0c; ring 的第 j个字符与 12:00 方向对齐的最少步数&#xff08;下标均从 0 开始&…...

Qt应用软件【协议篇】UDP示例

UDP协议简介 UDP(用户数据报协议)是一种无连接的网络协议,提供了简单但是不可靠的消息传输服务。与TCP不同,UDP不保证数据包的顺序、重复性或者可达性,但它在速度和效率上具有优势,特别适合那些对实时性要求高的应用,如视频流、在线游戏等。 Qt中的UDP编程 在Qt中,U…...

MyBatis之动态代理实现增删改查以及MyBatis-config.xml中读取DB信息文件和SQL中JavaBean别名配置

MyBatis之环境搭建以及实现增删改查 前言实现步骤1. 编写MyBatis-config.xml配置文件2. 编写Mapper.xml文件&#xff08;增删改查SQL文&#xff09;3. 定义PeronMapper接口4. 编写测试类1. 执行步骤2. 代码实例3. 运行log 开发环境构造图总结 前言 上一篇文章&#xff0c;我们…...

百面嵌入式专栏(面试题)内存管理相关面试题1.0

沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇我们将介绍内存管理相关面试题 。 一、内存管理相关面试题 page数据结构中的_refcount和_mapcount有什么区别?匿名页面和高速缓存页面有什么区别?page数据结构中有一个锁,我们称为页锁,请问trylock_page()和loc…...

SpringMVC 1.请求参数检查 2.全局异常处理 3.请求参数封装为Pojo

ErrorEnum.java // 枚举所有的错误 package com.example.demo.enums;import lombok.Getter;public enum ErrorEnum {SYSTEM_ERROR(-1, "系统错误"),PARAM_ERROR(-2, "参数错误"),OK(0, "成功"),;Getterprivate final int code;Getterprivate fi…...

7机器人位姿的数学描述与坐标变

由上次刚体的空间转动直接切换为机器人相关术语。 1.机器人位姿的数学描述与坐标变换 1.1位姿描述 {B}相对于{A}的姿态描述用3x3矩阵表示为&#xff1a; 式中为三个单位正交主矢量&#xff0c;分别表示刚体坐标系{B}的三个坐标轴XBYBZB在参考系{A}中的方位&#xff0c;∠XBXA表…...

基于ESP8266 开发板(MCU)遥控小车

遥控小车 ​ 遥控界面 ​ 【项目源码】 第一版ESP8266 https://github.com/liyinchigithub/esp8266_car_webServerhttps://github.com/liyinchigithub/esp8266_car_webServer 第二版ESP32 GitHub - liyinchigithub/esp32-wroom-car: 嵌入式单片机 ESP32 Arduino 遥控小车&a…...

【C生万物】C语言数据类型、变量和运算符

&#x1f4da;博客主页&#xff1a;爱敲代码的小杨. ✨专栏&#xff1a;《Java SE语法》 | 《数据结构与算法》 | 《C生万物》 ❤️感谢大家点赞&#x1f44d;&#x1f3fb;收藏⭐评论✍&#x1f3fb;&#xff0c;您的三连就是我持续更新的动力❤️ &#x1f64f;小杨水平有…...

CTF--Web安全--SQL注入之‘绕过方法’

一、什么是绕过注入 众所周知&#xff0c;SQL注入是利用源码中的漏洞进行注入的&#xff0c;但是有攻击手段&#xff0c;就会有防御手段。很多题目和网站会在源码中设置反SQL注入的机制。SQL注入中常用的命令&#xff0c;符号&#xff0c;甚至空格&#xff0c;会在反SQL机制中…...

线程池常用的阻塞队列

新任务来的时候&#xff0c;会先判断当前运行的线程数量是否达到核心线程数&#xff0c;如果达到的话&#xff0c;新任务就会被存放在队列中。 不同的线程池会选用不同的阻塞队列&#xff0c;我们可以结合内置线程池来分析。 ● 容量为 Integer.MAX_VALUE 的 LinkedBlockingQue…...

【Java EE】----SpringBoot的日志文件

1.SpringBoot使用日志 先得到日志对象通过日志对象提供的方法进行打印 2.打印日志的信息 3.日志级别 作用&#xff1a; 可以筛选出重要的信息不同环境实现不同日志级别的需求 ⽇志的级别分为&#xff1a;&#xff08;1-6级别从低到高&#xff09; trace&#xff1a;微量&#…...

【网络安全】2024年暗网威胁分析及发展预测

暗网因其非法活动而臭名昭著&#xff0c;现已发展成为一个用于各种非法目的的地下网络市场。 它是网络犯罪分子的中心&#xff0c;为被盗数据交易、黑客服务和邪恶活动合作提供了机会。为了帮助企业组织更好地了解暗网发展形势&#xff0c;近日&#xff0c;卡巴斯基的安全研究…...

SpringMVC-组件解析

一、引子 我们在上一篇文章Spring MVC-基本概念中&#xff0c;为读者解释了如何使用SpringMVC框架&#xff0c;将承接客户端请求的工作从原生的Servlet转移到我们熟知的Controller中。那么我们不禁会好奇&#xff0c;SpringMVC框架到底做了什么&#xff0c;是怎么把请求分发给…...

ubuntu22.04@laptop OpenCV Get Started: 002_reading_writing_videos

ubuntu22.04laptop OpenCV Get Started: 002_reading_writing_videos 1. 源由2. Read/Display/Write应用Demo3 video_read_from_file3.1 C应用Demo3.2 Python应用Demo3.3 重点过程分析3.3.1 读取视频文件3.3.2 读取文件信息3.3.3 帧读取&显示 4 video_read_from_image_sequ…...

Elasticsearch(ES) 简述请求操作索引下文档 增删查改操作

上文 Elasticsearch(ES) 创建带有分词器规则的索引 带着大家创建了一个带有分词功能的索引 老规矩 我们启动一下ES服务 本文 我们就来说说 关于文档的操作 我们先来添加一个文档 就像数据库加一条数据一样 这里 并不需要指定什么表结构和数据结构 它的文档结构是无模式的 添…...