设备搜索相关协议使用

一、实现原理

  1. 首先,Client -> Gateway : 发送 UDP 广播包(含厂商自定义协议)这一步表示客户端开始向网络中发送一个包含厂商自定义协议的 UDP 广播包,目的是寻找本厂商的设备(网关)。客户端此时处于活动状态activate Client,而网关开始等待接收广播包,也进入活动状态activate Gateway
  2. 当网关接收到符合厂商协议的广播包后,Gateway -> Client : 回复 UDP 包(若符合厂商协议),向客户端回复一个 UDP 包,告知自己的存在。之后客户端和网关的 UDP 交互暂时结束,状态变为不活动deactivate Clientdeactivate Gateway
  3. 接着,网关会在自己这一端Gateway -> Gateway : 建立 TCP 服务器,等待客户端的连接。当客户端准备好后,Client -> Gateway : 发起 TCP 连接,向网关发起 TCP 连接请求。网关收到请求后,Gateway -> Client : 接受 TCP 连接,接受客户端的连接,此时两者建立起了 TCP 长连接。
  4. 建立连接后,客户端可以向网关Client -> Gateway : 问询信息,询问所需的信息,网关收到请求后Gateway -> Client : 返回信息,将相应的信息返回给客户端。
  5. 然后,客户端可能需要向网关发送点表文件,即Client -> Gateway : 发送点表文件,网关接收文件后Gateway -> Client : 接收点表文件确认,向客户端返回接收确认信息。
  6. 最后,为了保持连接的活跃性,客户端会定期向网关Client -> Gateway : 发送心跳包,网关收到后Gateway -> Client : 回应心跳包,表示连接仍然正常。

二、相关协议

1、设备搜索协议

客户端—>搜索响应进程

客户端发送自定义标识,比如厂家名称字符串,这里自行协定

搜索响应进程—>客户端

设备收到协定的字符串校验成功后,回复"yes"

2、交互协议

这里的通信是基于TCP完成的,格式是json。通过type字段来标定事务类型,type取值如下(可以继续扩展):

1:获取运行时必要的参数信息
2:点表下发
3:心跳包

3、运行状态请求协议

客户端运行后首先下发此请求包,确认设备端是否已经有了点表配置文件。如果没有,那么下一步就是给设备下发点表文件;如果设备已经有了(下发过),那么需要获取设备的某些配置信息,以便QT后续运行使用。 ** 客户端--->搜索响应进程**
{"type": 1
}

** 搜索响应进程--->客户端** 设备出厂时候肯定是没有点表信息的,所以需要客户端下发,那么此时给客户端的回复up_config字段为true,后续的data无需添加。如果设备判断已经有这个点表了,那么up_config字段应该为false,并且把QT所需要的一些配置发回,添加上data字段(设备中的配置永远是最新的)。
{"type": 1,"result": 0, //成功返回0,失败返回1"up_config": false, //是否需要下发点表 true:需要下发,false:不需要下发"data": {  //配置信息,当up_config为true时不需要加data字段,false需增加此字段"mqtt_config":{"mqtt_addr": "192.168.1.2",  //mqtt服务器的地址"mqtt_port": 1883  //mqtt的端口      },"video_config":{"video_addr":"192.168.8.8", //监控服务的地址"video_port":8888 //监控服务的端口      },"update_config":{"type":1, //上报模式 0-不上报,客户端主动采集;1-变化上报,即连续2次值不相等;2-周期上报"period": 5 //上报周期时间,单位秒,仅在type=2时需要增加},xxx  //按需可继续添加}
}

4、配置下发协议
如果设备需要客户端下发点表配置文件(设备首次运行),那么在上述协议交互后,客户端会进行配置下发请求。
客户端文件下发是一个很常规的操作,比如配置文件、后期的升级文件都可以用这种方式进行。这里我们模仿下真正的FTP协议的流程来完成文件传输,参考下面的思想。
FTP端口号20和21的区别是21端口用于连接,20端口用于传输数据。进行FTP文件传输时,客户端首先连接到FTP服务器的21端口,进行用户的认证。认证成功后,要传输文件时,服务器会专门开一个新的端口20,来进行传输数据文件。所以传输文件时,实际上是一路新的链接,传输成功后,客户端会主动断开这一路链接。
所以,我们也模仿这个流程,可以定义8000端口专门用来做命令的控制,而8001这个端口来做文件的传输。
提示:一个进程是可以同时建立多个TCP链路的,所以这个流程我们可以保持8000端口的链路常开,当收到文件传输命令后,再开启一路8001socket端口监听,等待文件传输完成后,再关闭掉这路socket。FTP的思想就是文件传输链路随用随开,用完即关。FTP也常用在固件升级等场景中,下发的文件可能会很大。
两个端口的处理你可以用多线程、多进程、IO多路复用,这些思路都可以,只要能实现就行,下面给出一个select和线程结合的例子,仅作为参考。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>#define N 64typedef struct sockaddr SA;//这个例子里模拟了两个端口的响应,第一个端口用8888,第二个用6666
//模型用的select配合着线程实现的,仅作为参考void *new_sock(void *arg)
{printf("will recv new connect\n");int sockfd, clientfd;char buf[N];int addrlen = sizeof(struct sockaddr);struct sockaddr_in addr, clientaddr;int nbytes;// 1创建一个套接字--socketsockfd = socket(AF_INET, SOCK_STREAM, 0);if (sockfd < 0){perror("socket err");exit(-1);}// 2定义套接字地址--sockaddr_inbzero(&addr, addrlen);addr.sin_family = AF_INET;addr.sin_addr.s_addr = INADDR_ANY;addr.sin_port = htons(6666);  //新的连接用6666端口// 3绑定套接字--bindif (bind(sockfd, (struct sockaddr *)&addr, addrlen) < 0){perror("bind err");exit(-1);}// 4启动监听--listenif (listen(sockfd, 5) < 0){perror("listen err");exit(-1);}// 5接收连接--acceptclientfd = accept(sockfd, (struct sockaddr *)&clientaddr, &addrlen);if (clientfd < 0){perror("accept err");exit(-1);}printf("recv new client\n");// 6收发数据--recv/sendwhile (1) {nbytes = recv(clientfd, buf, N, 0);if(nbytes < 0) {perror("recv err");exit(-1);} else if (nbytes > 0) {printf("recv %s-%d data = %s\n", inet_ntoa(clientaddr.sin_addr), \ntohs(clientaddr.sin_port), buf);} else {printf("peer exit\n");break;}}}int main(int argc, char *argv[])
{// 1.定义变量int i, listenfd, connfd, maxfd, n;char buf[N];fd_set rdfs, rdtmp;struct sockaddr_in myaddr;if (argc < 3){puts("server <addr> <port>");return -1;}// 2.创建套接字并监听if ((listenfd = socket(PF_INET, SOCK_STREAM, 0)) < 0){perror("socket err");exit(-1);}bzero(&myaddr, sizeof(myaddr));myaddr.sin_family = AF_INET;myaddr.sin_addr.s_addr = INADDR_ANY;myaddr.sin_port = htons(8888);  //第一个链接用8888if (bind(listenfd, (SA *)&myaddr, sizeof(myaddr)) < 0){perror("fail to bind");exit(-1);}listen(listenfd, 5);// 3.更新最大文件描述符,并设置关注集maxfd = listenfd;FD_ZERO(&rdfs);          // 清空关注列表FD_SET(listenfd, &rdfs); // 将fd放入关注列表中while (1){rdtmp = rdfs;// 5.调用select进行监听if (select(maxfd + 1, &rdtmp, NULL, NULL, NULL) < 0){perror("select err");exit(-1);}// 遍历集合,如果服务器句柄有数据,那么代表有连接进来,把它加入描述符集并更新maxfd// 否则代表客户端句柄有数据,那么接收数据,如果对端退出,那么把它从描述符集清除for (i = 0; i < maxfd + 1; i++){if (FD_ISSET(i, &rdtmp)){if (i == listenfd){ // 表示有新连接进来connfd = accept(listenfd, NULL, NULL);FD_SET(connfd, &rdfs);if (connfd > maxfd){maxfd = connfd;}}else{ // 客户端有数据bzero(buf, N);n = recv(i, buf, N, 0);if (n > 0){printf("recv from %d--%s\n", i, buf); // 记得加\n冲刷缓冲区if (strncmp(buf, "new", 3) == 0){// 新建一个新的服务器,这里如果还想保证8888的端口客户端正常响应,必须开线程,否则会阻塞到新的操作中pthread_t tid;pthread_create(&tid, NULL, new_sock, NULL);}}else if (n == 0){FD_CLR(i, &rdfs);close(i);}else{}}}}}return 0;
}

客户端—>搜索响应进程

{"type": 2, "data": {"flag":"start",  // start:准备发送 data:文件数据  stop:发送完毕"file_name":"node.json",  //点表文件名,flag为start需要填写"file_len":560 //点表文件长度,flag为start需要填写}
}

搜索响应进程—>客户端
只有当flag为"start"或者"stop"时,需要回复;

{"type": 2"data": {"flag":"start"  // start:准备接收  stop:接收完成}
}

说明:当客户端收到start请求帧的回复后,就会连接网关的8001端口,进行文件的传输。网关需要根据请求帧的信息来完成文件的命名。当文件传输完成后,客户端会主动断开8001的TCP链接,并通过控制链路发送stop帧告知已经发送完成。设备收到stop帧后关闭文件,然后回复stop帧完成点表的下发请求。

5、心跳协议

心跳机制是用来检测和设备的连接的,如果连接正常,那么客户端会回复。
心跳包疑惑解释
客户端—>搜索响应进程

{"type": 3
}

搜索响应进程—>客户端

{  
"type": 3,"result": 0, //无需回复任何东西,回复即代表活着
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/463995.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

视频去水印怎么办?两种方法教会你

视频有水印的话确实很恼火&#xff0c;想要干净的去除视频水印&#xff0c;这里分享两种简单又实用的方法。 方法一&#xff1a;美图秀秀 大家都熟悉的修图神器&#xff0c;功能超全。不仅能把照片P得美美哒&#xff0c;还能去掉照片和视频上的水印呢&#xff01;用起来挺顺手…

【案例】旗帜飘动

开发平台&#xff1a;Unity 6.0 开发工具&#xff1a;Shader Graph 参考视频&#xff1a;Unity Shader Graph 旗帜飘动特效   一、效果图 二、Shader Graph 路线图 三、案例分析 核心思路&#xff1a;顶点偏移计算 与 顶点偏移忽略 3.1 纹理偏移 视觉上让旗帜保持动态飘动&a…

PHP合成图片,生成海报图,poster-editor使用说明

之前写过一篇使用Grafika插件生成海报图的文章&#xff0c;但是当我再次使用时&#xff0c;却发生了错误&#xff0c;回看Grafika文档&#xff0c;发现很久没更新了&#xff0c;不兼容新版的GD&#xff0c;所以改用了intervention/image插件来生成海报图。 但是后来需要对海报…

智慧汇聚:十款企业培训工具打造学习型企业

在当今快速变化的商业环境中&#xff0c;企业要想保持竞争力&#xff0c;就必须不断适应新技术、新市场和新的工作方式。构建一个学习型企业&#xff0c;不仅能够促进员工的个人成长&#xff0c;还能增强团队的整体能力和企业的创新能力。为了实现这一目标&#xff0c;借助先进…

「C/C++」C/C++标准库 之 #include<cstdlib> 通用工具函数库

✨博客主页何曾参静谧的博客&#x1f4cc;文章专栏「C/C」C/C程序设计&#x1f4da;全部专栏「VS」Visual Studio「C/C」C/C程序设计「UG/NX」BlockUI集合「Win」Windows程序设计「DSA」数据结构与算法「UG/NX」NX二次开发「QT」QT5程序设计「File」数据文件格式「PK」Parasoli…

pycharm调用方法时显示为灰色

不用担心&#xff0c;亮的证明是被用过得&#xff0c;灰色的没有被用&#xff0c;引用一下就会变正常了

机器学习:我们能用机器学习来建立投资模型吗

机器学习模型能解决什么投资问题&#xff1f; 利用机器学习解决投资问题的思路&#xff0c;其实和在互联网领域解决推荐、广告问题的思路是一样的&#xff0c;只不过利用的特征完全变了。推荐、广告模型利用的是用户的年龄、性别&#xff0c;物品的类别、价格等特征&#xff0c…

ClkLog企业版(CDP)预售开启,更有鸿蒙SDK前来助力

新版本发布 ClkLog在上线近1年后&#xff0c;获得了客户的一致肯定与好评&#xff0c;并收到了不少客户对功能需求的反馈。根据客户的反馈&#xff0c;我们在今年三季度对ClkLog的版本进行了重新的规划与调整&#xff0c;简化了原有的版本类型&#xff0c;方便客户进行选择。 与…

【Java设计模式】16-26章

行为型模式&#xff1a; 第16章 12模板方法模式(Template) 16.1 豆浆制作问题 16.2 模板方法模式基本介绍 16.3 模板方法模式原理类图 16.4 模板方法模式解决豆浆制作问题 package com.atguigu.template;//抽象类&#xff0c;表示豆浆 public abstract class SoyaMilk {//模板…

上市公司环境信息披露质量评分数据王婉菁版(2008-2023年)噪声光污染辐射废水减排等治理

数据来源基础数据来源于上市公司年报、社会责任报告、环境报告以及证监会和统计局。时间跨度2008-2023区域跨度企业及行业层面 核心解释变量&#xff1a;环境信息披露质量&#xff0c;是由上市公司环境管理、负债、业绩于治理、披露载体等各项信息披露质量评分加总。 被解释变…

Llama 3.2 Vision Molmo:多模态开源生态系统基础

编者按&#xff1a; 视觉功能的融入对模型能力和推理方式的影响如何&#xff1f;当我们需要一个既能看懂图像、又能生成文本的 AI 助手时&#xff0c;是否只能依赖于 GPT-4V 这样的闭源解决方案&#xff1f; 我们今天为大家分享的这篇文章&#xff0c;作者的核心观点是&#xf…

el-table 滚动条重置 手动控制滚动条

最近在使用 el-table 的时候&#xff0c;出现一个问题&#xff1a; 表头过长的时候&#xff0c;会有左右滑动的操作&#xff0c;当我们把表格拉到最右侧&#xff0c;这个时候重新请求数据的话&#xff0c;表格位置还是在最右侧&#xff0c;不会恢复原位。 那我们想恢复原位&a…

Windows的MySQL开机自动启动问题

标题 问题描述 问题描述 在Windows系统中&#xff0c;我设置好了MySQL服务为自动启动&#xff0c;但在开机后发现MySQL服务任没有自动运行。我有点苦恼&#xff0c;每次连接MySQL&#xff0c;都要进入计算机管理&#xff0c;手动打开。 解决方法&#xff1a; 1.前提安装好MySQ…

私有化视频平台EasyCVR视频汇聚平台接入RTMP协议推流为何无法播放?

私有化视频平台EasyCVR视频汇聚平台兼容性强、支持灵活拓展&#xff0c;平台可提供视频远程监控、录像、存储与回放、视频转码、视频快照、告警、云台控制、语音对讲、平台级联等视频能力。 有用户反馈&#xff0c;项目现场使用RTMP协议接入EasyCVR平台&#xff0c;但是视频却不…

Python小白学习教程从入门到入坑------第二十三课 封装(语法进阶)

面向对象的三大特征&#xff1a;封装、继承、多态 一、封装 1.1 何为封装 封装&#xff1a;在Python中指的是隐藏对象中一些不希望被外部所访问到的属性或者方法。将复杂的信息、流程给包起来&#xff0c;内部处理&#xff0c;让使用者只需要通过简单的操作步骤&#xff0c;…

Rust 力扣 - 643. 子数组最大平均数 I

文章目录 题目描述题解思路题解代码题目链接 题目描述 题解思路 我们遍历长度为k的窗口&#xff0c;我们只需要记录窗口内的最大和即可&#xff0c;遍历过程中刷新最大值 结果为窗口长度为k的最大和 除以 k 题解代码 impl Solution {pub fn find_max_average(nums: Vec<…

Vscode使用launch.json进行传参调试代码

目录 1 操作2 后记 1 操作 {// Use IntelliSense to learn about possible attributes.// Hover to view descriptions of existing attributes.// For more information, visit: https://go.microsoft.com/fwlink/?linkid830387"version": "0.2.0","…

Fooocus图像生成软件本地部署教程:在Windows上快速上手AI创作

文章目录 前言1. 本地部署Fooocus图像生成软件1.1 安装方式1.2 功能介绍 2. 公网远程访问Fooocus3. 固定Fooocus公网地址 前言 本篇文章将介绍如何在本地Windows11电脑部署开源AI生图软件Fooocus&#xff0c;并结合Cpolar内网穿透工具轻松实现公网环境远程访问与使用。 Foooc…

#渗透测试#SRC漏洞挖掘#自动化脚本的编写01

免责声明 本教程仅为合法的教学目的而准备&#xff0c;严禁用于任何形式的违法犯罪活动及其他商业行为&#xff0c;在使用本教程前&#xff0c;您应确保该行为符合当地的法律法规&#xff0c;继续阅读即表示您需自行承担所有操作的后果&#xff0c;如有异议&#xff0c;请立即停…

python 使用进程池并发执行 SQL 语句

这段代码使用了 Python 的 multiprocessing 模块来实现真正的并行处理&#xff0c;绕过 Python 的全局解释器锁&#xff08;GIL&#xff09;限制&#xff0c;从而在多核 CPU 上并发执行多个 SQL 语句。 from pyhive import hive import multiprocessing# 建立连接 conn hive.…