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

【LuatOS】基于WebSocket的同步请求框架

0x00 缘起

由于使用LuatOS PC模拟器发起快速且海量HTTP请求(1000 次/秒)时,会耗尽PC的TCP连接资源,而无法进行继续进行访问请求。故使用WebSocket搭建类似于HTTP的“同步请求相应”的通信框架,以实现与HTTP类似的功能。

0x01 服务端

服务端使用Go搭建WebSocket服务器,其代码示意如下:

package mainimport ("log""net""net/http""time"
)var upgrader = websocket.Upgrader{ReadBufferSize:  1024,WriteBufferSize: 1024,
}// HandleEchoHello 进行简单回应
func HandleEchoHello(w http.ResponseWriter, r *http.Request) {conn, err := upgrader.Upgrade(w, r, nil)if err != nil {fmt.Println("升级到WebSocket失败:", err)return}defer conn.Close()for {_, message, err := conn.ReadMessage()if err != nil {fmt.Println("读取消息失败:", err)break}receiveTimestamp := time.Now().UnixNano()sendTimestamp, err := strconv.ParseInt(string(message), 10, 64)if err != nil {sendTimestamp = 0}delayTimestampNs := float64(receiveTimestamp - sendTimestamp)delayTimestampMs := delayTimestampNs / 1000000.0res := "sendTime: " + string(message) + ", " + "receiveTime:" + strconv.FormatInt(receiveTimestamp, 10) + ", delay: " + strconv.FormatFloat(delayTimestampMs, 'f', -1, 64) + "ms"// 返回值r, _ := json.Marshal(map[string]interface{}{"message":    res,"statusCode": 200,})// 发送回客户端的消息err = conn.WriteMessage(websocket.TextMessage, r)if err != nil {fmt.Println("发送消息失败:", err)break}}
}func main() {http.HandleFunc("/", HandleEchoHello)err := http.ListenAndServe(":8080", nil)if err != nil {log.Panic("WebSocket服务器启动失败:", err.Error())return}log.Println("WebSocket服务器运行在:http://localhost:8080")
}

上述Go代码在8080端口开启了一个WebSocket服务器等待连接,客户端连接服务器后可以发送自己的纳秒时间戳测试其传输时间,若LuatOS PC模拟器不支持纳秒,可以为LuatOS PC模拟器添加高精度时间戳获取功能或者使用Lua Socket所提供的微秒。

0x02 客户端

以下代码是使用WebSocket所封装的同步请求框架,其在发送数据后必须等到服务器返回数据后才会进行下一次发送作业。

-- SyncWebScoket.lualocal SWS = {}
SWS.__index = SWSlocal tag = "SyncWebScoket"function SWS.create(address, port)local wsc_recv_buffer = {} local wsc_send_success_tag = falselocal wsc_recv_success_tag = falselocal wsc = nillocal connected = falselocal self = setmetatable({}, SWS) function self:connect()if connected thenlog.info(tag, "Already connected.")return connectedendlog.info(tag, "Connecting to " .. address .. ":" .. port)if not wsc thenwsc = websocket.create(nil, address .. ":" .. port)wsc:on(function(wsc, event, data, fin, optcode)if event == "recv" thentable.insert(wsc_recv_buffer, data)if fin == 1 then               wsc_recv_success_tag = true endendif event == "conack" then connected = trueendif event == "disconnect" thenconnected = falseendif event == "sent" thenwsc_send_success_tag = trueendend)endwsc:connect()local count = 0while not connected dosys.wait(100)count = count + 1if count >= 10 thenbreakendendif connected thenlog.info(tag, "Connected")wsc:autoreconn(true, 3000) elselog.error(tag, "Failed To Connect.")endreturn connectedend-- 断开连接方法function self:disconnect()log.info(tag, "Disconnecting from " .. address .. ":" .. port)wsc:autoreconn(false)wsc:close()wsc = nilconnected = falsereturn trueendfunction self:send(data)if not connected thenlog.error(tag, "Cannot send data, not connected.")return falseendwsc_recv_buffer = {}wsc_send_success_tag = falsewsc_recv_success_tag = falsewsc:send(data)local count = 0while not wsc_send_success_tag dosys.wait(1)count = count + 1if count >= 1000 thenbreakendendif not wsc_send_success_tag thenlog.error(tag, "Send Data Failed, Please Check The Internet.")return falseendlocal count = 0while not wsc_recv_success_tag dosys.wait(1)count = count + 1if count >= 1000 thenbreakendendif not wsc_recv_success_tag thenlog.error(tag, "Receive Data Failed.")return falseendlocal message = ""                        for _, value in ipairs(wsc_recv_buffer) do if type(value) ~= "string" thenlog.error(tag, "Error parsing WebSocket data!")return falseendmessage = message .. valueendreturn true, messageendreturn self
endreturn SWS

上述代码为基于WebSocket的同步请求框架SyncWebSocket,在main.lua的使用如下:

-- main.luaPROJECT = "sync_websocket_test"
VERSION = "1.0.0"_G.sys = require("sys")local TAG = PROJECTlocal swc = require("SyncWebScoket") Host = "127.0.0.1"
Port = "8080"local swsc = swc.create(Host, Port) sys.taskInit(function()sys.waitUntil("IP_READY")  -- 默认都等到联网成功-- 连接SyncWebSocketwhile not swsc:connect() dosys.wait(100)endlog.info(TAG, "SWSC 连接成功!")sys.publish("swsc_conok")
end)sys.taskInit(function()sys.waitUntil("swsc_conok")log.info(TAG, "开始服务端与客户端传输时间测试...")local startTime = timeplus.getnanosecond()for i = 1, 10000, 1 do -- 发送10次,测试一下传输时间local result, message = swsc:send(timeplus.getnanosecond())if result thenlog.info(TAG, tostring(i) .. " Message: " .. message)endendlocal endTime = timeplus.getnanosecond()-- 计算时间差并转换为毫秒local startTimeNum = tonumber(startTime)local endTimeNum = tonumber(endTime)-- 计算差值并转换为毫秒local timeDifferenceMs = (endTimeNum - startTimeNum) / 1000000000.0print("consumeTime: " .. endTime .. "-" .. startTime .. "=" .. tostring(timeDifferenceMs) .. "s")
end)sys.run()

上述main.lua代码展示了SyncWebSocket框架的使用方法,其中timeplus.getnanosecond()是为LuatOS编译添加的获取纳秒字符串的方法,可以替换成其他时间戳库进行测试,客户端以及服务端代码仅作为思路说明,不对其运行效果进行保证。

0x03 资源

  • LuatOS WebSoket 官方文档

0x04 后记

  • 己欲立而立人,己欲达而达人。

相关文章:

【LuatOS】基于WebSocket的同步请求框架

0x00 缘起 由于使用LuatOS PC模拟器发起快速且海量HTTP请求(1000 次/秒)时,会耗尽PC的TCP连接资源,而无法进行继续进行访问请求。故使用WebSocket搭建类似于HTTP的“同步请求相应”的通信框架,以实现与HTTP类似的功能…...

架构师考试系列(8)论文专题:信息系统安全设计

摘要 2021年4月,我公司承接了一款健康养老系统项目,旨在提供以健康养老为核心的管理平台。本文探讨了如何在系统开发中贯彻安全优先原则,保障系统的安全性和保密性。系统包括健康档案、照护计划、服务审计、健康状况跟踪、费用管理等功能模块。我作为系统架构设计师,负责了…...

浙大一附院就医:分享给大家工作久了关节疼的就医经验,腱鞘炎

症状描述:日常生活不影响,但左手手腕往前或者往后扭曲力度过大时会有痛感。 医嘱详情:腱鞘炎,可能是工作键盘打字久了导致,开了三盒药贴,一盒三片,一共9片,另外再买一个比较硬的护腕…...

如何降低 PCIe RTT?

以下是一些降低 PCIe RTT(往返时间)的方法: 硬件方面4: 优化主板设计与布局: 合理分配 PCIe 通道:确保不同的 PCIe 设备被分配到独立的、互不干扰的 PCIe 通道上。例如,如果主板上有多个 PCIe 插…...

数据结构之二叉树--前序,中序,后序详解(含源码)

二叉树 二叉树不能轻易用断言,因为树一定有空 二叉树链式结构的实现 在学习二叉树的基本操作前,需先要创建一棵二叉树,然后才能学习其相关的基本操作。 typedef int BTDataType; typedef struct BinaryTreeNode {BTDataType _data;struct B…...

红黑树及MySQL 基础架构

红黑树简介及左旋、右旋、变色 红黑树(Red Black Tree)是一种自平衡二叉搜索树(二叉查找树),是一种特殊的二叉搜索树,在进行插入和删除时通过特定操作保持二叉树自身的平衡,从而获得较高的查找性能。 红黑树的平衡操作通过左旋、右旋和变色来…...

大数据-212 数据挖掘 机器学习理论 - 无监督学习算法 KMeans 基本原理 簇内误差平方和

点一下关注吧!!!非常感谢!!持续更新!!! 目前已经更新到了: Hadoop(已更完)HDFS(已更完)MapReduce(已更完&am…...

QJson-趟过的各种坑(先坑后用法)

QJson-趟过的各种坑【先坑后用法】 Chapter1 QJson-趟过的各种坑【先坑后用法】一、不能处理大数据量,如果你的数据量有百兆左右(特别是有的小伙伴还喜欢json格式化输出的),不要用Qjson,否则会报错 DocumentTooLarge二、json格式化输出1.构建…...

基于STM32的hx711称重模块使用

欢迎入群共同学习交流 时间记录:2024/11/9 一、知识点记录 1、hx711 1)HX711是一款高精度压力传感器专用的24位模数转换芯片,主要功能是将测得的微小电压信号放大到可以被微控制器读取的范围 2)工作电压2.6-5.5V 3)引…...

Nginx独立项目相关配置说明

配置前说明 1. 部署环境为https环境的,除华为云表态托管等都需要此配置,如cloud。 2. 部署环境为https环境的,可以使用api.js直接访问后端服务,无需此配置。 3. 转发的后台服务接口需要和后台人员沟通确认一致。详细配置说明 **…...

Nuxt3之使用lighthouse性能测试及性能优化实操

lighthouse性能测试工具 什么是 LightHouse 呢 Lighthouse 是一个开源的自动化工具,用于提高网页的质量。可以通过浏览器的开发者工具运行,也可以作为命令行工具或 Node.js 模块集成到持续集成系统中。Lighthouse 可以帮助开发者: 性能优化…...

‌webdriver.Chrome()参数简介

webdriver.Chrome()参数‌如下: ‌executable_path‌:指定ChromeDriver的路径,若未设置且系统环境变量中已配置,则会自动寻找。‌options‌:通过webdriver.ChromeOptions()创建,用于设定浏览器的启动选项&…...

Ubuntu如何更换环境中的Python版本

Ubuntu Python 版本迁移指南 卸载 Python 3.8 # 移除 Python 3.8 sudo apt remove python3.8# 清理依赖 sudo apt autoremove# 清理缓存 sudo apt clean安装 Python 3.10 # 更新软件包列表 sudo apt update# 安装软件源管理工具 sudo apt install software-properties-commo…...

python-字符串中大写字母转小写,小写字母转大写

平时我们进行大小写转换基本都是使用upper和lower函数,使用方法: s Hello,Python123#大写转小写 s.lower() -->hello,python123#小写转大写 s.upper() -->HELLO,PYTHON123但是如果想把字符串中的大写字母转成小写,小写字母转成大写&a…...

前端学习之ES6+

1.ES6是什么 ES6,全称是ECMAScript 6,是JavaScript语言的下一代标准,由ECMA国际组织在2015年6月正式发布。ES6也被称作ECMAScript 2015,从这个版本开始,ECMA组织决定每年发布一个新的ECMAScript版本,以使J…...

yolov10的几种权重文件

1.官方提供的几种模型权重文件 YOLOv10官网提供的权重文件是训练好的网络各层的权值,这些权值是通过训练集训练出来的。‌一旦网络训练完成,应用时只需加载这些权值,而不再需要原始的训练集。这意味着,如果你已经配置好了环境&am…...

FPGA视频GTH 8b/10b编解码转PCIE3.0传输,基于XDMA中断架构,提供工程源码和技术支持

目录 1、前言工程概述免责声明 2、相关方案推荐我已有的PCIE方案我已有的 GT 高速接口解决方案 3、PCIE基础知识扫描4、工程详细设计方案工程设计原理框图输入Sensor之-->芯片解码的HDMI视频数据组包基于GTH高速接口的视频传输架构GTH IP 简介GTH 基本结构GTH 发送和接收处理…...

C++类和对象 (下)

文章目录 前言一. 再探构造函数初始化列表特性总结练习 二. 类型转换2.1 隐式类型转换2.2 临时对象具有常性2.3 explicit关键字2.4 多参数类型转化 三. static成员概念特性练习 四. 友元概念特性 五. 内部类概念特性 六. 匿名对象概念特性 七. 对象拷贝时的编译器优化END 前言 …...

网络层5——IPV6

目录 一、IPv6 vs IPv4 1、对IPv6主要变化 2、IPv4 vs IPv6 二、IPv6基本首部 1、版本——4位 2、通信量类——8位 3、流标号——20位 4、有效载荷长度——16位 5、下一个首部——8位 6、跳数限制——8位 7、源 、 目的地址——128位 8、扩展首部 三、IPv6地址 1…...

【wpf】ResourceDictionary 字典资源的用法

如果你的字典资源是写在启动项目的App.xaml里 <Application.Resources><ResourceDictionary><ResourceDictionary.MergedDictionaries><ResourceDictionary Source"pack://application:,,,/YourNonStartupProject;component/Resources/SharedResour…...

<6>-MySQL表的增删查改

目录 一&#xff0c;create&#xff08;创建表&#xff09; 二&#xff0c;retrieve&#xff08;查询表&#xff09; 1&#xff0c;select列 2&#xff0c;where条件 三&#xff0c;update&#xff08;更新表&#xff09; 四&#xff0c;delete&#xff08;删除表&#xf…...

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...

Python:操作 Excel 折叠

💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...

微信小程序 - 手机震动

一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注&#xff1a;文档 https://developers.weixin.qq…...

SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现

摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序&#xff0c;以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务&#xff0c;提供稳定高效的数据处理与业务逻辑支持&#xff1b;利用 uniapp 实现跨平台前…...

Android15默认授权浮窗权限

我们经常有那种需求&#xff0c;客户需要定制的apk集成在ROM中&#xff0c;并且默认授予其【显示在其他应用的上层】权限&#xff0c;也就是我们常说的浮窗权限&#xff0c;那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...

HarmonyOS运动开发:如何用mpchart绘制运动配速图表

##鸿蒙核心技术##运动开发##Sensor Service Kit&#xff08;传感器服务&#xff09;# 前言 在运动类应用中&#xff0c;运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据&#xff0c;如配速、距离、卡路里消耗等&#xff0c;用户可以更清晰…...

并发编程 - go版

1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程&#xff0c;系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...

MySQL 8.0 事务全面讲解

以下是一个结合两次回答的 MySQL 8.0 事务全面讲解&#xff0c;涵盖了事务的核心概念、操作示例、失败回滚、隔离级别、事务性 DDL 和 XA 事务等内容&#xff0c;并修正了查看隔离级别的命令。 MySQL 8.0 事务全面讲解 一、事务的核心概念&#xff08;ACID&#xff09; 事务是…...

掌握 HTTP 请求:理解 cURL GET 语法

cURL 是一个强大的命令行工具&#xff0c;用于发送 HTTP 请求和与 Web 服务器交互。在 Web 开发和测试中&#xff0c;cURL 经常用于发送 GET 请求来获取服务器资源。本文将详细介绍 cURL GET 请求的语法和使用方法。 一、cURL 基本概念 cURL 是 "Client URL" 的缩写…...