gsoap工具生成onvif设备搜索(remotediscovery)代码框架

2023-05-16

什么是gsoap工具?

gSOAP 提供了两个工具来方便开发人员使用 C/C++ 语言快速开发Web 服务应用,通过 gSOAP 提供的这两个工具,开发人员可以快速生成服务端与客户端代码框架,接下来开发人员只需要实现具体的接口函数即可。

gSOAP工具可以在Windows、Linux和Macosx操作系统下运行,gSOAP工具包中自带有Windows和Macosx操作系统的wsdl2h和soapcpp2可执行文件。wsdl2h 工具根据 WSDL 文件生成 C/C++ .h 头文件;soapcpp2 工具则从上面生成的头文件生成 SOAP 服务端和客户端框架代码。

gSOAP开源版下载网址(最新版本):gSOAP Toolkit download | SourceForge.net

======================================================

1、制作编译文件夹

下载gSOAP工具,进行解压。创建一个文件夹onvif1,从gSOAP工具中拷贝如下文件和文件夹到onvif1文件夹中:

soap_2.8\gsoap-2.8\gsoap\bin\win32\soapcpp2.exe
gsoap_2.8\gsoap-2.8\gsoap\bin\win32\wsdl2h.exe
gsoap_2.8\gsoap-2.8\gsoap\stdsoap2.c
gsoap_2.8\gsoap-2.8\gsoap\stdsoap2.h
gsoap_2.8\gsoap-2.8\gsoap\typemap.dat
gsoap_2.8\gsoap-2.8\gsoap\import\
gsoap_2.8\gsoap-2.8\gsoap\custom\

还有一个onvif模块wsdl文件remotediscovery.wsdl,也放入该目录下。

=====================================================

2、进行wsdl2h编译,得到的文件onvif.h

wsdl2h 工具根据 WSDL 文件生成 C/C++ .h 头文件。
WSDL(Web Service Description Language)即 Web 服务描述语言,它使用 XML 来对 Web 服务进行描述。进入电脑的cmd环境,进入刚才创建的onvif1目录。
wsdl2h 的用法:


格式用法: wsdl2h -o 头文件名 WSDL文件名或URL

在本篇中,主要使用gSOAP工具在Windows操作系统下生成onvif协议的设备搜索代码框架,的wsdl2h和soapcpp2可执行文件,onvif设备搜索的WSDL文件的URL地址为:

RemoteDiscovery(设备发现)
https://www.onvif.org/ver10/networ/wsdl/remotediscovery.wsdl

方法一

本篇中在C:\WINDOWS\system32\cmd.exe中使用URL的wsdlh2的命令为:


wsdl12h -P -x -c -s -t ./typemap.dat -o samples/onvif/onvif.h https://www.onvif.org/ver10/networ/wsdl/remotediscovery.wsdl

方法二

在C:\WINDOWS\system32\cmd.exe中不使用模块的URL,可以先下载需要使用的onvif模块,命令行后加上模块名,这样wsdlh2的命令为:


wsdl2h -o onvif.h -c -s -t ./typemap.dat remotediscovery.wsdl 

-c为产生纯c代码,默认生成 c++代码;

-s为不使用STL库,

-t为typemap.dat的标识。

onvif模块wsdl文件下载地址为:

https://download.csdn.net/download/weixin_44651073/87580490

运行结束后,得到变异的c++头文件(onvif.h)

=================================================================

3、进行soapcpp2编译,由c++文件生成onvif 的设备搜索代码框架

soapcpp2 工具则从上面生成的头文件生成 SOAP 服务端和客户端框架代码。例如对于上面的cacl.h,使用 soapcpp2 命令:


soapcpp2 -2 -c onvif.h -I .\custom -I .\import -I .\import

soapcpp2 也支持额外的参数:

-i 生成 C++ 包装类,客户端为 xxxProxy.h(.cpp),服务端为xxxService.h(.cpp)
-I 指定 import 的路径,比如需要引入stlvector.h文件来支持 STL vector 的序列化
-C 仅生成客户端代码
-S 仅生成服务端代码
-c 产生纯 C 代码,否则是 C++ 代码
-x 不要产生 XML 示例文件
-L 不要产生soapClientLib.c和soapServerLib.c文件

最后运行的结果为:

命令的其他参数详细说明如下:

可以使用命令wsdl2h.exe -help查看

E:\onvif1>wsdl2h.exe -help
Usage: wsdl2h [-a] [-b] [-c|-c++|-c++11|-c++14|-c++17] [-D] [-d] [-e] [-F] [-f] [-g] [-h] [-I path] [-i] [-j] [-k] [-L] [-l] [-M] [-m] [-N name] [-n name] [-O1|-O2|-O3|-O4|-Ow2|-Ow3|-Ow4] [-P|-p] [-Q] [-q name] [-R] [-r proxyhost[:port[:uid:pwd]]] [-r:uid:pwd] [-Sname] [-s] [-T] [-t typemapfile] [-U] [-u] [-V] [-v] [-w] [-W] [-x] [-y] [-z#] [-_] [-o outfile.h] infile.wsdl infile.xsd http://www... ...

-a      generate indexed struct names for local elements with anonymous types
-b      bi-directional operations (duplex ops) added to serve one-way responses
-c      generate C source code
-c++    generate C++ source code (default)
-c++11  generate C++11 source code
-c++14  generate C++14 source code
-c++17  generate C++17 source code
-D      make attribute members with default/fixed values optional with pointers
-d      use DOM to populate xs:any, xs:anyType, and xs:anyAttribute
-e      don't qualify enum names
-F      add transient members to structs to simulate struct-type derivation in C
-f      generate flat C++ class hierarchy by removing inheritance
-g      generate global top-level element and attribute declarations
-h      display help info and exit
-Ipath  use path to locate WSDL and XSD files
-i      don't import (advanced option)
-j      don't generate SOAP_ENV__Header and SOAP_ENV__Detail definitions
-k      don't generate SOAP_ENV__Header mustUnderstand qualifiers
-L      generate less documentation by removing generic @note comments
-l      display license information
-M      suppress error "must understand element with wsdl:required='true'"
-m      use xsd.h module to import primitive types
-Nname  use name for service prefixes to produce a service for each binding
-nname  use name as the base namespace prefix instead of 'ns'
-O1     optimize by omitting duplicate choice/sequence members
-O2     optimize -O1 and omit unused schema types (unreachable from roots)
-O3     optimize -O2 and omit unused schema root attributes
-O4     optimize -O3 and omit unused schema root elements (use only with WSDLs)
-Ow2    optimize -O2 while retaining all derived types of used base types
-Ow3    optimize -O3 while retaining all derived types of used base types
-Ow4    optimize -O4 while retaining all derived types of used base types
-ofile  output to file
-P      don't create polymorphic types inherited from xsd__anyType
-p      create polymorphic types inherited from base xsd__anyType
-Q      make xsd__anySimpleType equal to xsd__anyType to use as the base type
-qname  use name for the C++ namespace of all declarations
-R      generate REST operations for REST bindings specified in a WSDL
-rhost[:port[:uid:pwd]]
        connect via proxy host, port, and proxy credentials uid and pwd
-r:uid:pwd
        connect with authentication credentials uid and pwd
-Sname  use name instead of 'soap' for the C++ class members with soap contexts
-s      don't generate STL code (no std::string and no std::vector)
-tfile  use type map file instead of the default file typemap.dat
-U      allow UTF-8-encoded Unicode C/C++ identifiers when mapping XML tag names
-u      don't generate unions
-V      display the current version and exit
-v      verbose output
-W      suppress warnings
-w      always wrap response parameters in a response struct (<=1.1.4 behavior)
-X      don't qualify part names to disambiguate doc/lit wrapped patterns
-x      don't generate _XML any/anyAttribute extensibility elements
-y      generate typedef synonyms for structs and enums
-z1     compatibility with 2.7.6e: generate pointer-based arrays
-z2     compatibility with 2.7.7-2.7.15: (un)qualify element/attribute refs
-z3     compatibility with 2.7.16-2.8.7: (un)qualify element/attribute refs
-z4     compatibility up to 2.8.11: don't generate union structs in std::vector
-z5     compatibility up to 2.8.15: don't include minor improvements
-z6     compatibility up to 2.8.17: don't include minor improvements
-z7     compatibility up to 2.8.59: don't generate std::vector of class of union
-z8     compatibility up to 2.8.74: don't gen quals for doc/lit wrapped patterns
-z9     compatibility up to 2.8.93: always qualify element/attribute refs
-z10    compatibility up to 2.8.96: gen quals even when defined w/o namespace
-_      don't generate _USCORE (replace with Unicode code point _x005f)
infile.wsdl infile.xsd http://www... list of input sources (if none reads stdin)

 

 在生成的onvif.h代码中,要修改上面生成的onvif.h: 在onvif.h头文件开头加入:#import "wsse.h"    

为了方便,我们将所有需要的代码放到同一个目录中。我们在刚才建立的onvif1目录下创建一个application目录,存放我们需要的所有代码。

比如soap下生成的soapC.cpp、soapClient.cpp、soapH.h、soapStub.h、wsdd.nsmap;gsoap源码目录下的stdsoap2.cpp、stdsoap2.h;gsoap/plugin目录下的wsseapi.h、wsseapi.cpp、smdevp.h、smdevp.cpp、mecevp.cpp、mecevp.h、threads.cpp、threads.h、wsaapi.cpp、wsaapi.h等。并创建一个main.cpp(注意,如果只有.c没有.cpp的,那么就将其拷贝到application目录下,然后将尾部改成.cpp):

=========================================================================

main.cpp的代码工程:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifdef WIN32
#include <winsock.h>
#else
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <unistd.h>
#endif

/* 从技术层面来说,通过单播、多播、广播三种方式都能探测到IPC,但多播最具实用性*/
#define COMM_TYPE_UNICAST         1                                             // 单播
#define COMM_TYPE_MULTICAST       2                                             // 多播
#define COMM_TYPE_BROADCAST       3                                             // 广播
#define COMM_TYPE                 COMM_TYPE_MULTICAST

/* 发送探测消息(Probe)的目标地址、端口号 */
#if COMM_TYPE == COMM_TYPE_UNICAST
    #define CAST_ADDR "100.100.100.15"                                          // 单播地址,预先知道的IPC地址
#elif COMM_TYPE == COMM_TYPE_MULTICAST
    #define CAST_ADDR "239.255.255.250"                                         // 多播地址,固定的239.255.255.250
#elif COMM_TYPE == COMM_TYPE_BROADCAST
    #define CAST_ADDR "100.100.100.255"                                         // 广播地址
#endif

#define CAST_PORT 3702                                                          // 端口号

/* 以下几个宏是为了socket编程能够跨平台,这几个宏是从gsoap中拷贝来的 */
#ifndef SOAP_SOCKET
# ifdef WIN32
#  define SOAP_SOCKET SOCKET
#  define soap_closesocket(n) closesocket(n)
# else
#  define SOAP_SOCKET int
#  define soap_closesocket(n) close(n)
# endif
#endif

#if defined(_AIX) || defined(AIX)
# if defined(_AIX43)
#  define SOAP_SOCKLEN_T socklen_t
# else
#  define SOAP_SOCKLEN_T int
# endif
#elif defined(SOCKLEN_T)
# define SOAP_SOCKLEN_T SOCKLEN_T
#elif defined(__socklen_t_defined) || defined(_SOCKLEN_T) || defined(CYGWIN) || defined(FREEBSD) || defined(__FreeBSD__) || defined(OPENBSD) || defined(__QNX__) || defined(QNX) || defined(OS390) || defined(__ANDROID__) || defined(_XOPEN_SOURCE)
# define SOAP_SOCKLEN_T socklen_t
#elif defined(IRIX) || defined(WIN32) || defined(__APPLE__) || defined(SUN_OS) || defined(OPENSERVER) || defined(TRU64) || defined(VXWORKS) || defined(HP_UX)
# define SOAP_SOCKLEN_T int
#elif !defined(SOAP_SOCKLEN_T)
# define SOAP_SOCKLEN_T size_t
#endif

#ifdef WIN32
#define SLEEP(n)    Sleep(1000 * (n))
#else
#define SLEEP(n)    sleep((n))
#endif

/* 探测消息(Probe),这些内容是ONVIF Device Test Tool 15.06工具搜索IPC时的Probe消息,通过Wireshark抓包工具抓包到的 */
const char *probe = "<?xml version=\"1.0\" encoding=\"utf-8\"?><Envelope xmlns:dn=\"http://www.onvif.org/ver10/network/wsdl\" xmlns=\"http://www.w3.org/2003/05/soap-envelope\"><Header><wsa:MessageID xmlns:wsa=\"http://schemas.xmlsoap.org/ws/2004/08/addressing\">uuid:fc0bad56-5f5a-47f3-8ae2-c94a4e907d70</wsa:MessageID><wsa:To xmlns:wsa=\"http://schemas.xmlsoap.org/ws/2004/08/addressing\">urn:schemas-xmlsoap-org:ws:2005:04:discovery</wsa:To><wsa:Action xmlns:wsa=\"http://schemas.xmlsoap.org/ws/2004/08/addressing\">http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe</wsa:Action></Header><Body><Probe xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns=\"http://schemas.xmlsoap.org/ws/2005/04/discovery\"><Types>dn:NetworkVideoTransmitter</Types><Scopes /></Probe></Body></Envelope>";

int main(int argc, char **argv)
{
    int ret;
    int optval;
    SOAP_SOCKET s;
    SOAP_SOCKLEN_T len;
    char recv_buff[4096] = {0};
    struct sockaddr_in multi_addr;
    struct sockaddr_in client_addr;

#ifdef WIN32
    WSADATA wsaData;
    if( WSAStartup(MAKEWORD(2,2), &wsaData) != 0 ) {                             // 初始化Windows Sockets DLL
        printf("Could not open Windows connection.\n");
        return 0;
    }
    if ( LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2 ) {
        printf("the version of WinSock DLL is not 2.2.\n");
        return 0;
    }
#endif

    s = socket(AF_INET, SOCK_DGRAM, 0);                                         // 建立数据报套接字
    if (s < 0) {
        perror("socket error");
        return -1;
    }

#if COMM_TYPE == COMM_TYPE_BROADCAST
    optval = 1;
    ret = setsockopt(s, SOL_SOCKET, SO_BROADCAST, (const char*)&optval, sizeof(int));
#endif

    multi_addr.sin_family = AF_INET;                                            // 搜索IPC:使用UDP向指定地址发送探测消息(Probe)
    multi_addr.sin_port = htons(CAST_PORT);
    multi_addr.sin_addr.s_addr = inet_addr(CAST_ADDR);
    ret = sendto(s, probe, strlen(probe), 0, (struct sockaddr*)&multi_addr, sizeof(multi_addr));
    if (ret < 0) {
        soap_closesocket(s);
        perror("sendto error");
        return -1;
    }
    printf("Send Probe message to [%s:%d]\n\n", CAST_ADDR, CAST_PORT);
    SLEEP(1);

    for (;;) {                                                                  // 接收IPC的应答消息(ProbeMatch)
        len = sizeof(client_addr);
        memset(recv_buff, 0, sizeof(recv_buff));
        memset(&client_addr, 0, sizeof(struct sockaddr));
        ret = recvfrom(s, recv_buff, sizeof(recv_buff) - 1, 0, (struct sockaddr*)&client_addr, &len);
        printf("===Recv ProbeMatch from [%s:%d]===\n%s\n\n",  inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port), recv_buff);
        SLEEP(1);
    }
    soap_closesocket(s);

    return 0;
}

 

 


 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

gsoap工具生成onvif设备搜索(remotediscovery)代码框架 的相关文章

随机推荐

  • sprintf和printf 用法的区别

    printf 的作用是标准化输出 xff0c 默认的对象是标准输出缓冲区 xff0c 要有一定的条件才能把缓冲区里面的数据输出 sprintf 作用是格式化输出函数 xff0c 保存字符串到缓冲区中 xff0c 起到拼接字符串的作用 功能
  • select函数实现TCP双向通信

    服务器通信实现代码 include 34 myhead h 34 tcp双向通信 服务器的代码 多路复用使用思路 xff1a 1 思考要监测什么文件描述符 新的套接字 接收 键盘 发生 2 监测新套接字的读就绪 监测键盘的读就绪 int m
  • C++调用构造函数,后面用冒号添加变量的作用

    C 43 43 调用构造函数和成员函数后 xff0c 在函数的后面添加一个冒号的含义 首先知道初始化机制中 xff0c 有两种赋值机制 xff0c 有赋值运算符赋值和括号赋值 xff1a 传统赋值 xff1a int a 61 10 int
  • 第六篇,STM32脉冲宽度调制(PWM)编程

    1 PWM概念 PWM叫脉冲宽度调制 Pulse Width Modulation xff0c 通过编程控制输出方波的频率和占空比 高低电平的比例 xff0c 广泛应用在测量 xff0c 通信 xff0c 功率控制等领域 呼吸灯 xff0c
  • ovn 配置逻辑路由器实现三层转发

    本文使用ovn搭建一个三层转发的环境 xff0c 拓扑图如下 image png 两个虚拟交换机ls1和ls2 xff0c 端口ip网段分别为 10 10 10 0 24和 10 10 20 0 24 虚拟交换机上分别连接两个vm 使用na
  • 第十篇,STM32串口蓝牙编程

    1 串口蓝牙概念 串口蓝牙是一个蓝牙模块 xff0c 内部有蓝牙模块和程序 xff0c 可以进行蓝牙通信 xff0c 同时提供一个串口接口 xff0c 通过串口可以配置蓝牙模块进行数据传输 2 使用串口3连接蓝牙模块 3 手机上安装蓝牙调试
  • 第十四篇,STM32的CAN总线通信

    1 CAN总线的概念 CAN指的是控制器局域网网络 Controller Area Network xff0c 由德国博世汽车电子厂商开发出来 CAN使用差分信号 xff0c 具有较强的抗干扰能力和传输稳定性 CAN属于多主通信 xff0c
  • OpenCV图像处理学习十九,像素重映射cv::remap

    一 像素重映射概念 重映射就是把输入图像中各个像素按照制定的规则顺序映射到另外一张图像的对应位置上去 xff0c 形成一张新的图像 二 像素映射API函数接口 cv remap xff08 InputArray src 输入图像 Outpu
  • OpenCV图像处理学习二十一,直方图比较方法

    一 直方图比较 直方图比较是对输入的两张图像进行计算得到直方图H1与H2 xff0c 归一化到相同的尺度空间 xff0c 然后可以通过计算H1与H2的之间的距离得到两个直方图的相似程度 xff08 每张图像都有唯一的直方图与之对应 xff0
  • 嵌入式FreeRTOS学习八,xTaskCreate创建任务的细节以及恢复中断任务实现

    一 创建任务函数xTaskCreate 任务也不是很复杂的东西 xff0c 任务也就是一个函数xTaskCreate 简单得说 xff0c 创建一个任务 xff0c 你得提供它的执行函数 xff0c 你得提供它的栈的大小 xff0c 函数的
  • 嵌入式FreeRTOS学习一,FreeRTOS概述和代码结构

    一 FreeRTOS是什么 FreeRTOS 是由 Real Time Engineers Ltd 出品 xff0c 是一款市场领先的 RTOS 现在已经支持几十种 处理器架构 Free即免费的 xff0c RTOS全称是 Real Tim
  • 嵌入式FreeRTOS学习二,FreeRTOS任务的创建和删除

    一 任务的创建和删除 1 1 函数xTaskCreate 此函数用来创建一个任务 xff0c 任务需要RAM来保存与任务有关的状态信息 任务控制块 xff0c 任务也需要一定的RAM 来作为任务堆栈 如果使用函数xTaskCreate 来创
  • 嵌入式FreeRTOS学习五,FreeRTOS任务调度器

    四 调度器 FreeRTOS 操作系统支持三种调度方式 xff1a 抢占式调度 xff0c 时间片调度和合作式调度 实际应用主要是抢占式调度和时间片调度 xff0c 合作式调度用到的很少 启动调度器的API函数vTaskStartSched
  • 嵌入式FreeRTOS学习九,任务链表的构成,TICK时间中断和任务状态切换调度

    一 tskTaskControlBlock 函数结构体 在tskTaskControlBlock 任务控制块结构体中 xff0c 其中有任务状态链表和事件链表两个链表成员 xff0c 首先介绍任务状态链表这个结构 xff0c 这个链表通常用
  • 嵌入式FreeRTOS学习十,任务调度和任务就绪链表任务调度过程

    一 main函数里面的栈是哪里分配的 main函数里面用到的栈 xff0c 假设为msp 是汇编代码里面设定的 xff0c 对于STM32F103 在汇编代码里的向量表设置了一个栈 initial sp 那这个栈是给谁用的呢 xff1f 可
  • ovn 通过网关虚拟路由器连接外部网络

    本文实验如何通过ovn的网关逻辑路由器将ovn网络连接到外部网络 前面讲过ovn的逻辑路由器是分布式的 xff0c 这意味着它没有绑定到某个节点上 xff0c 而是存在于所有节点上的 xff0c 同时它是通过每个节点的openflow流表来
  • 嵌入式FreeRTOS学习十一,深入理解任务调度机制

    一 任务调度机制 可抢占 xff1a 高优先级的任务先运行时间片轮转 xff1a 同优先级的任务轮流执行空闲任务礼让 xff1a 如果有同是优先级为0的其他就绪任务 xff0c 空闲任务主动放弃一次运行机会函数调用vTaskDelay xD
  • SOAP传输协议

    一 HTTP传输协议 超文本传输协议 xff08 HyperText Transfer Protocol xff0c 缩写 xff1a HTTP xff09 xff0c 它是基于请求 响应的模式协议 xff0c 客户端发出请求 xff0c
  • ONVIF简介

    一 什么是ONVIF ONVIF规范描述了网络视频的模型 接口 数据类型以及数据交互的模式 并复用了一些现有的标准 xff0c 如WS系列标准等 ONVIF规范的目标是实现一个网络视频框架协议 xff0c 使不同厂商所生产的网络视频产品 x
  • gsoap工具生成onvif设备搜索(remotediscovery)代码框架

    什么是gsoap工具 xff1f gSOAP 提供了两个工具来方便开发人员使用 C C 43 43 语言快速开发Web 服务应用 xff0c 通过 gSOAP 提供的这两个工具 xff0c 开发人员可以快速生成服务端与客户端代码框架 xff