gsoap工具生成onvif设备搜索(remotediscovery)代码框架-程序员宅基地

技术标签: gsoap  onvif设备搜索  onvif网络视频协议  onvif网络视屏协议  

什么是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;
}

 

 


 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_44651073/article/details/129564238

智能推荐

http隧道 java_使用java语言实现http隧道技术-程序员宅基地

文章浏览阅读119次。该楼层疑似违规已被系统折叠隐藏此楼查看此楼/***Getaparametervalue**@paramkeyString*@paramdefString*@returnString*/publicStringgetParameter(Stringkey,Stringdef){returnisStandalone?System.getProperty(ke..._java http隧道

Keepalived高可用+邮件告警_keepalived sendmail-程序员宅基地

文章浏览阅读913次。IP主机名备注192.168.117.14keepalived-master主节点192.168.117.15keepalived-slaver备节点192.168.117.100VIP1.主备节点均安装keepalived# yum install -y keepalived httpd2.主备节点均修改keepalived日志存放路径..._keepalived sendmail

SPFILE 错误导致数据库无法启动(ORA-01565)_ora01565 ora27046-程序员宅基地

文章浏览阅读469次。--==========================================--SPFILE错误导致数据库无法启动(ORA-01565)--========================================== SPFILE错误导致数据库无法启动 SQL> startup ORA-01078: failurein proce_ora01565 ora27046

功能测试基础知识(1)-程序员宅基地

文章浏览阅读6.1k次,点赞2次,收藏54次。功能测试基础知识总结_功能测试

postgresql 中文排序_pg中文排序-程序员宅基地

文章浏览阅读3.2k次,点赞3次,收藏2次。pg 中文首字母排序_pg中文排序

[Mysql] CONVERT函数_mysql convert-程序员宅基地

文章浏览阅读3.1w次,点赞23次,收藏109次。本文主要讲解CONVERT函数_mysql convert

随便推点

HTML5与微信开发(2)-视频播放事件及API属性_微信开发者工具视频快进-程序员宅基地

文章浏览阅读8.6k次,点赞2次,收藏2次。HTML5 的视频播放事件想必大家已经期待很久了吧,在HTML4.1、4.0之前我们如果在网页上播放视频无外乎两种方法: 第一种:安装FLASH插件或者微软发布的插件 第二种:在本地安装播放器,在线播放组件之类的 因为并不是所有的浏览器都安装了FLASH插件,就算安装也不一定所有的都能安装成功。像苹果系统就是默认禁用FLASH的,安卓虽然一开始的时候支持FLASH,但是在安卓4.0以后也开始不_微信开发者工具视频快进

JedisConnectionException Connection Reset_jedisconnectionexception: java.net.socketexception-程序员宅基地

文章浏览阅读5.4k次,点赞3次,收藏4次。在使用redis的过程常见错误总结1.JedisConnectionException Connection Reset参考这边文章:Connection reset原因分析和解决方案https://blog.csdn.net/cwclw/article/details/527971311.1问题描述Exception in thread "main" redis.clients...._jedisconnectionexception: java.net.socketexception: connection reset

Lua5.3版GC机制理解_lua5.3 gc-程序员宅基地

文章浏览阅读8.3k次,点赞8次,收藏42次。目录1.Lua垃圾回收算法原理简述2.Lua垃圾回收中的三种颜色3.Lua垃圾回收详细过程4.步骤源码详解4.1新建对象阶段4.2触发条件4.3 GC函数状态机4.4标记阶段4.5清除阶段5.总结参考资料lua垃圾回收(Garbage Collect)是lua中一个比较重要的部分。由于lua源码版本变迁,目前大多数有关这个方面的文章都还是基于lua5.1版本,有一定的滞后性。因此本文通过参考当前..._lua5.3 gc

手机能打开的表白代码_能远程打开,各种手机电脑进行监控操作,最新黑科技...-程序员宅基地

文章浏览阅读511次。最近家中的潮人,老妈闲着没事干,开始学玩电脑,引起他的各种好奇心。如看看新闻,上上微信或做做其他的事情。但意料之中的是电脑上会莫名出现各种问题?不翼而飞的图标?照片又不见了?文件被删了,卡机或者黑屏,无声音了,等等问题。常常让她束手无策,求助于我,可惜在电话中说不清,往往只能苦等我回家后才能解决,那种开心乐趣一下子消失了。想想,这样也不是办法啊, 于是,我潜心寻找了两款优秀的远程控制软件。两款软件...

成功Ubuntu18.04 ROS melodic安装Cartograhper+Ceres1.13.0,以及错误总结_ros18.04 安装ca-程序员宅基地

文章浏览阅读1.8k次。二.初始化工作空间三.设置下载地址四.下载功能包此处可能会报错,请看:rosdep update遇到ERROR: error loading sources list: The read operation timed out问题_DD᭄ꦿng的博客-程序员宅基地接下来一次安装所有功能包,注意对应ROS版本 五.编译功能包isolated:单独编译各个功能包,每个功能包之间不产生依赖。编译过程时间比较长,可能需要几分钟时间。此处可能会报错:缺少absl依赖包_ros18.04 安装ca

Harbor2.2.1配置(trivy扫描器、镜像签名)_init error: db error: failed to download vulnerabi-程序员宅基地

文章浏览阅读4.1k次,点赞3次,收藏7次。Haobor2.2.1配置(trivy扫描器、镜像签名)docker-compose下载https://github.com/docker/compose/releases安装cp docker-compose /usr/local/binchmod +x /usr/local/bin/docker-composeharbor下载https://github.com/goharbor/harbor/releases解压tar xf xxx.tgx配置harbor根下建立:mkd_init error: db error: failed to download vulnerability db: database download

推荐文章

热门文章

相关标签