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

实习日志30

概要

高拍仪硬件通信原理,WebSocket源码解析(JavaScript)

WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。

WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

在 WebSocket API 中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。

现在,很多网站为了实现推送技术,所用的技术都是 Ajax 轮询。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP请求,然后由服务器返回最新的数据给客户端的浏览器。这种传统的模式带来很明显的缺点,即浏览器需要不断的向服务器发出请求,然而HTTP请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,显然这样会浪费很多的带宽等资源。

HTML5 定义的 WebSocket 协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。

ps:本来想写sm4加密和解密算法的,但是sm3一个加密都看的我头昏昏的,就先不为难自己了,说说WebSocket的源码解析吧

源自: HTML5 WebSocket | 菜鸟教程 (runoob.com)

整体架构流程

拟人化展示从HTTP协议升级到WebSocket协议的过程:

1、发送一个GET请求
关键: Upgrade: websocket; Connection: Upgrade;
这两个就告诉服务器,我要发起websocket协议,我不是HTTP。

2、服务器收到了协议,返回一个 Switching Protocol, 这样就连接成功了。

3、接下来的通信都是websocket, 这样就很好的连接了。

源自:WebSocket建立连接的过程_websocket如何建立连接-CSDN博客

 

技术名词解释

连接请求:Connection: Upgrade;

通信消息数据:(二进制消息)

技术细节

一、建立连接:

在高拍仪初始化时建立连接

初始化,设置显示相机屏幕大小,设置自动裁剪(初始化后才能设置)

function LoadCameraDocument() {if (!window.WebSocket) {alert("浏览器不支持HTML5,请更新浏览器或者使用其它浏览器");}//console.log("LoadCameraDocument");var obj = document.getElementById("CameraCtl");Cam_ControlInit(obj, 0, 0, 600, 400);// 模拟异步硬件初始化setTimeout(function () {// 设置自动裁剪SetCameraCutMode();}, 2500); // 假设2.5秒后硬件初始化完成// 模拟异步硬件初始化setTimeout(function () {// 设置自动裁剪SetCameraCutMode();}, 5000); // 完不成再来一下
}

 连接WebSocket,初始化相机

//*************摄像头操作初始化***************
function Cam_ControlInit(documentObj, mX, mY, mwidth, mheight) {WebSocketConnect();InitCanvas(documentObj, mX, mY, mwidth, mheight);//console.log("Cam_ControlInit");
}

 设置连接地址和开启时函数,

        设置心跳检测、断线重连、获取设备数目

        完成后输出连接成功 "socket.onopen"

socket = new WebSocket("ws://127.0.0.1:22225");
socket.binaryType = "arraybuffer";socket.onopen = function (event) {//heartCheck.reset().start(); heartCheck();isSocketConnect = true;clearInterval(intervalId);//if (isOpenMainCamera == false)         Cam_GetDevCount();console.log("socket.onopen");};

二、发送数据:

首先要有心跳,if (isSocketConnect)

其次,创建二进制数组 var aDataArray = new Uint8Array(totalLen)

然后,消息分装

最后,发送二进制消息 socket.send(aDataArray.buffer);

示例“处理拍照逻辑发送消息逻辑”代码:


function CaptureImage(fileAddr) {if (isSocketConnect) {// var pathArray = stringToUint8Array(fileAddr);if (fileAddr == "") {var packageCount = 1;var len = 0;var pindex = 0;var totalLen = 12;var aDataArray = new Uint8Array(totalLen);aDataArray[0] = 0x77;aDataArray[1] = 0x88;aDataArray[2] = 0x10;aDataArray[3] = 0x00;aDataArray[4] = len >> 16 & 0xff;aDataArray[5] = len >> 8 & 0xff;aDataArray[6] = len & 0xff;aDataArray[7] = packageCount >> 8 & 0xff;   //包总数aDataArray[8] = packageCount & 0xff;   //包总数aDataArray[9] = 0;   //分包长度aDataArray[10] = pindex >> 8 & 0xff;   //包序号aDataArray[11] = pindex & 0xff;    //包序号console.log("pindex:" + pindex);socket.send(aDataArray.buffer);} else {var path = encodeURI(fileAddr);//console.log(path);var pathArray = stringToByte(path);var len = pathArray.length;var packageCount = 0;var tmpLen = len;while (tmpLen > 0) {tmpLen = tmpLen - 90;packageCount++;}console.log("packageCount:" + packageCount);var pindex = 0;tmpLen = len;while (tmpLen > 0) {tmpLen = tmpLen - 90;if (tmpLen > 0) {var totalLen = 90 + 12;var aDataArray = new Uint8Array(totalLen);aDataArray[0] = 0x77;aDataArray[1] = 0x88;aDataArray[2] = 0x10;aDataArray[3] = 0x00;aDataArray[4] = len >> 16 & 0xff;aDataArray[5] = len >> 8 & 0xff;aDataArray[6] = len & 0xff;aDataArray[7] = packageCount >> 8 & 0xff;   //包总数aDataArray[8] = packageCount & 0xff;   //包总数aDataArray[9] = 90;   //分包长度aDataArray[10] = pindex >> 8 & 0xff;   //包序号aDataArray[11] = pindex & 0xff;    //包序号console.log("pindex:" + pindex);for (var i = 0; i < 90; i++) {aDataArray[12 + i] = pathArray[i + pindex * 90];}socket.send(aDataArray.buffer);} else {var totalLen = 90 + tmpLen + 12;  // 此时tmpLen为负数,做加法运算var aDataArray = new Uint8Array(totalLen);aDataArray[0] = 0x77;aDataArray[1] = 0x88;aDataArray[2] = 0x10;aDataArray[3] = 0x00;aDataArray[4] = len >> 16 & 0xff;aDataArray[5] = len >> 8 & 0xff;aDataArray[6] = len & 0xff;aDataArray[7] = packageCount >> 8 & 0xff;   //包总数aDataArray[8] = packageCount & 0xff;   //包总数aDataArray[9] = 90 + tmpLen;   //分包长度aDataArray[10] = pindex >> 8 & 0xff;   //包序号aDataArray[11] = pindex & 0xff;    //包序号console.log("pindex:" + pindex);for (var i = 0; i < (90 + tmpLen); i++) {aDataArray[12 + i] = pathArray[i + pindex * 90];}socket.send(aDataArray.buffer);}pindex++;toSleep(80);}}}
}

三、响应数据:

例如:拍照时数据处理

创建onmessage方法,心跳检测必写

socket.onmessage = function (event) {// heartCheck.reset().start();      var rDataArr = new Uint8Array(event.data);if (rDataArr.length > 0) {// WebSocket心跳检测if (rDataArr[0] == 0x11 && rDataArr[1] == 0x11 && rDataArr[2] == 0x11) {console.log("socket心跳 ❤");}// 处理rDataArr数据// 省略...示例代码}}

响应数据方法:socket.onmessage = function (event) {}

示例"处理拍照结果返回响应逻辑"代码:

//拍照结果返回
if (rDataArr[2] == 0x10) {var flag;if (rDataArr[3] == 0x01) {flag = 0;var imgpathLen = rDataArr[4] * 256 + rDataArr[5];if (imgpathLen == 0) {var base64Len = rDataArr[6] * 65536 + rDataArr[7] * 256 + rDataArr[8];var imgPathStr = "";var base64Data = new Uint8Array(base64Len);for (var i = 0; i < base64Len; i++) {base64Data[i] = rDataArr[9 + imgpathLen + i];}var base64Str = Uint8ArrayToString(base64Data);GetCaptrueImgResultCB(flag, imgPathStr, base64Str);} else {var base64Len = rDataArr[6] * 65536 + rDataArr[7] * 256 + rDataArr[8];var pData = new Uint8Array(imgpathLen);for (var i = 0; i < imgpathLen; i++) {pData[i] = rDataArr[9 + i];}var str = byteToString(pData);var imgPathStr = decodeURIComponent(str);var base64Data = new Uint8Array(base64Len);for (var i = 0; i < base64Len; i++) {base64Data[i] = rDataArr[9 + imgpathLen + i];}var base64Str = Uint8ArrayToString(base64Data);GetCaptrueImgResultCB(flag, imgPathStr, base64Str);}}if (rDataArr[3] == 0x02) {flag = 2;GetCaptrueImgResultCB(flag, "", "");}}

小结

WebSocket是一种在Web浏览器和服务器之间进行全双工通信的协议,通过它可以实现实时的数据传输。建立WebSocket连接的过程包括发送一个GET请求并指定协议升级,服务器返回一个Switching Protocol响应,连接成功后即可进行WebSocket通信。在实际应用中,可以通过WebSocket发送和接收二进制消息来实现各种功能,例如拍照、传输文件等。需要注意的是,为了保持连接的稳定性,通常会实现心跳检测和断线重连功能。

  1. 深入理解WebSocket协议:通过实际编码,我更深入地理解了WebSocket协议的工作原理和建立连接的过程。

  2. 网络通信能力提升:通过处理WebSocket通信的逻辑,我提升了自己的网络通信能力,包括发送和接收数据的处理能力。

  3. 异步编程理解:WebSocket通信通常是异步的,我巩固了如何处理异步通信,例如通过回调函数处理接收到的消息。

  4. 实践经验:通过实际编写WebSocket通信相关的代码,我积累了宝贵的实践经验,可以帮助我更好地理解和应用相关知识。

  5. 问题解决能力:在编写过程中可能遇到了各种问题,通过解决这些问题,我提升了自己的问题解决能力和调试技巧。

相关文章:

实习日志30

概要 高拍仪硬件通信原理&#xff0c;WebSocket源码解析&#xff08;JavaScript&#xff09; WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。 WebSocket 使得客户端和服务器之间的数据交换变得更加简单&#xff0c;允许服务端主动向客户端推送数据…...

【MySQL】探索表结构、数据类型和基本操作

表、记录、字段 数据库的E-R&#xff08;entity-relationship&#xff0c;实体-关系&#xff09;模型中有三个主要概念&#xff1a; 实体集 、 属性 、 关系集 。 一个实体集对应于数据库中的一个表&#xff0c;一个实体则对应于数据库表 中的一行&#xff0c;也称为一条记录。…...

解决采集时使用selenium被屏蔽的办法

解决采集时使用selenium被屏蔽的办法 实用seleniumbase uc模式 from seleniumbase import Driver driver Driver(ucTrue) # 使用UC模式UC模式是基于undetected-chromedriver 但做了一些优化更新&#xff0c;使用起来更方便 官方例子&#xff1a; from seleniumbase import …...

stream流-> 判定 + 过滤 + 收集

List<HotArticleVo> hotArticleVos hotArticleVoList .stream() .filter(x -> x.getChannelId().equals(wmChannel.getId())).collect(Collectors.toList()); 使用Java 8中的Stream API对一个名为hotArticleVoList的列表进行过滤操作&#xff0c;筛选出符合指定条件…...

人工智能在测绘行业的应用与挑战

目录 一、背景 二、AI在测绘行业的应用方向 1. 自动化特征提取 2. 数据处理与分析 3. 无人机测绘 4. 智能导航与路径规划 5. 三维建模与可视化 6. 地理信息系统&#xff08;GIS&#xff09;智能化 三、发展前景 1. 技术融合 2. 精准测绘 3. 智慧城市建设 4. 可…...

四、分类算法 - 随机森林

目录 1、集成学习方法 2、随机森林 3、随机森林原理 4、API 5、总结 sklearn转换器和估算器KNN算法模型选择和调优朴素贝叶斯算法决策树随机森林 1、集成学习方法 2、随机森林 3、随机森林原理 4、API 5、总结...

pytorch -- DataLoader

定义 提供了给定数据集的迭代器 torch.utils.data.DataLoader(dataset, batch_size1, 每次拿多少数据 shuffleNone, 是否打乱 samplerNone, batch_samplerNone, num_workers0, 多进程&#xff08;加载数据时采用&#xff09;默认是0,使用主进程加载数据 collate_fnNone, p…...

【MySQL面试复习】索引创建的原则有哪些?

系列文章目录 在MySQL中&#xff0c;如何定位慢查询&#xff1f; 发现了某个SQL语句执行很慢&#xff0c;如何进行分析&#xff1f; 了解过索引吗&#xff1f;(索引的底层原理)/B 树和B树的区别是什么&#xff1f; 什么是聚簇索引&#xff08;聚集索引&#xff09;和非聚簇索引…...

四种主流的prompt框架

省流版&#xff1a; 文章介绍了在使用GPT时的四种prompt框架&#xff0c;有利于使用者打磨提问风格&#xff0c;与GPT进行更好的交互以提高生产力&#xff0c;能帮助大家有效提高工作效率~ 创作不易&#xff0c;如果对你有帮助的话&#xff0c;还请三连支持~ 想要使用Prompt…...

Educational Codeforces Round 160 (Rated for Div. 2) E. Matrix Problem(费用流)

原题链接&#xff1a;E. Matrix Problem 题目大意&#xff1a; 给出一个 n n n 行 m m m 列的 0 / 1 0/1 0/1 矩阵&#xff0c;再给出一些限制条件&#xff1a;一个长为 n n n 的数组 a a a&#xff0c;和一个长为 m m m 的数组 b b b 。 其中 a i a_{i} ai​ 表示第 …...

基于SpringBoot的气象数据监测分析大屏

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。这里根据疫情当下&#xff0c;你想解决的问…...

关于硅的制造芯片的过程

芯片是如何制作的&#xff1f; 先将硅融化制成硅晶片&#xff0c;再用光刻机印压电路。 bilibili芯片制作视频 硅晶片作为现代芯片的主要元件&#xff0c;广泛用于集成电路。 首先将多晶硅放入特制的密封炉&#xff0c;排除其中空气后加热到1420摄氏度&#xff0c;将融化的硅放…...

【深度学习笔记】3_10 多层感知机的PyTorch实现

注&#xff1a;本文为《动手学深度学习》开源内容&#xff0c;仅为个人学习记录&#xff0c;无抄袭搬运意图 3.10 多层感知机的简洁实现 下面我们使用PyTorch来实现上一节中的多层感知机。首先导入所需的包或模块。 import torch from torch import nn from torch.nn import …...

输入法在 Android13上候选词 候选区域 不显示的问题

背景 自研的输入法发现在 Android13 平台上不显示候选区域&#xff0c;在之前平台上以及需求是输入英文时不显示&#xff0c;中文需要显示。 最终解决办法&#xff1a;setExtractViewShown(false) Override public View onCreateCandidatesView() {...setExtractViewShown(f…...

Java 面向对象进阶 18 JDK8、9开始新增的方法;接口的应用;适配器设计模式;内部类(黑马)

一、JDK8开始新增的方法 默认方法不是抽象方法&#xff0c;所以不强制被重写&#xff1a; 但是如果被重写&#xff0c;就要去掉default关键字&#xff1a; public可以省略&#xff0c;但是default不可以省略&#xff1a; public是灰色的&#xff0c;代表可以省略 但是default是…...

数据结构-二分搜索树(Binary Search Tree)

一,简单了解二分搜索树 树结构: 问题:为什么要创造这种数据结构 1,树结构本身是一种天然的组织结构,就好像我们的文件夹一样,一层一层的. 2,树结构可以更高效的处理问题 二,二分搜索树的基础 1、二叉树 2,二叉树的重要特性 满二叉树 总结: 1. 叶子结点出现在二叉树的最…...

YOLO如何训练自己的模型

目录 步骤 一、打标签 二、数据集 三、跑train代码出模型 四、跑detect代码出结果 五、详细操作 步骤 一、打标签 &#xff08;1&#xff09;在终端 pip install labelimg &#xff08;2&#xff09;在终端输入labelimg打开 如何打标签&#xff1a; 推荐文章&#xf…...

05 EXTI外部中断

一、中断系统 中断系统&#xff1a;管理和执行中断的逻辑结构。中断&#xff1a;在主程序运行过程中&#xff0c;出现了特定的中断触发条件——中断源&#xff0c;使得CPU暂停当前正在运行的程序&#xff0c;转而去处理中断程序&#xff0c;处理完成后又返回原来被暂停的位置继…...

2024.2.23

1.1.1 信号默认、捕获、忽略处理(普通信号) #include <myhead.h> void handler(int signo) {if(signoSIGINT){printf("用户键入 ctrlc\n");} } int main(int argc, const char *argv[]) {//忽略信号if(signal(SIGINT,SIG_IGN)SIG_ERR){perror("signal er…...

PHP实现分离金额和其他内容便于统计计算

得到的结果可以粘贴到excel计算 <?php if($_GET["x"] "cha"){ $tips isset($_POST[tips]) ? $_POST[tips] : ; $pattern /(\d\.\d|\d)/; $result preg_replace($pattern, "\t\${1}\t", $tips); echo "<h2><strong>数…...

RestClient

什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端&#xff0c;它允许HTTP与Elasticsearch 集群通信&#xff0c;而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级&#xff…...

椭圆曲线密码学(ECC)

一、ECC算法概述 椭圆曲线密码学&#xff08;Elliptic Curve Cryptography&#xff09;是基于椭圆曲线数学理论的公钥密码系统&#xff0c;由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA&#xff0c;ECC在相同安全强度下密钥更短&#xff08;256位ECC ≈ 3072位RSA…...

DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径

目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...

VB.net复制Ntag213卡写入UID

本示例使用的发卡器&#xff1a;https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...

黑马Mybatis

Mybatis 表现层&#xff1a;页面展示 业务层&#xff1a;逻辑处理 持久层&#xff1a;持久数据化保存 在这里插入图片描述 Mybatis快速入门 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/6501c2109c4442118ceb6014725e48e4.png //logback.xml <?xml ver…...

鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/

使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题&#xff1a;docker pull 失败 网络不同&#xff0c;需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...

JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作

一、上下文切换 即使单核CPU也可以进行多线程执行代码&#xff0c;CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短&#xff0c;所以CPU会不断地切换线程执行&#xff0c;从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...

(转)什么是DockerCompose?它有什么作用?

一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用&#xff0c;而无需手动一个个创建和运行容器。 Compose文件是一个文本文件&#xff0c;通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...

ip子接口配置及删除

配置永久生效的子接口&#xff0c;2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列&#xff0c;以便知晓哪些列包含有价值的数据&#xff0c;…...