ONVIF协议网络摄像机(IPC)客户端程序开发(4):使用gSOAP生成Web Services框架代码

1. 专栏导读

本专栏第一篇文章「专栏开篇」列出了专栏的完整目录,按目录顺序阅读,有助于你的理解,专栏前面文章讲过的知识点(或代码段),后面文章不会赘述。为了节省篇幅,突出重点,在文章中展示的示例代码仅仅是关键代码,你可以在「专栏开篇」中获取完整代码。

如有错误,欢迎你的留言纠正!让我们共同成长!你的「点赞」「打赏」是对我最大的支持和鼓励!

2. 不要自己造轮子

ONVIF标准是使用SOAP方式实现的Web Services,本专栏上一篇文章已经介绍了什么是Web Services,涉及很多概念,包括SOAP、HTTP、XML,RPC等等。辣么多东东,全部要自己码代码实现吗?当然不用,我们不必自己造轮子,有现成的工具会帮我们自动生产大部分的代码框架。

这样的工具有很多,比如:

  1. gSOAP工具,适用于C/C++语言开发。
  2. Apache CXF工具,适用于JAVA语言开发者。

我的项目采用C/C++语言,所以本文重点讲解gSOAP。后面,网络摄像机(IPC)客户端程序代码都是使用gSOAP工具自动生成的,所以必须对gSOAP工具必须有一个深入的理解,为此,我们先从简单的例子开始理解。

3. gSOAP简介

gSOAP官方网址:http://www.cs.fsu.edu/~engelen/soap.html

gSOAP开源版下载网址(最新版本):http://sourceforge.net/projects/gsoap2

gSOAP开源版下载网址(历史版本):https://sourceforge.net/projects/gsoap2/files/gSOAP/

gSOAP有分商业版「commercial edition」和开源版「open source edition」,我撰写本专栏用的gSOAP是开源版「gsoap_2.8.45」。

gSOAP 编译工具提供了一个SOAP关于C/C++ 语言的实现,从而让C/C++语言开发Web Services服务端或客户端程序的工作变得轻松了很多。甚至,即使你对Web Services不甚了解都没有关系,有了gSOAP这样的工具,你也能开发基于SOAP方式实现的Web Services客户端。

gSOAP到底会自动生成哪些框架代码,下图中浅绿色框中的部分就是自动生成的代码。


图1

4. gSOAP工具转换原理


图2

gSOAP工具根据WSDL文档,自动生成C/C++语言的客户端/服务端框架代码。这其中有两个工具很重要,wsdl2h和soapcpp2。wsdl2h工具根据WSDL文成C/C++头文件,而soapcpp2工具则是根据该头文件生成C/C++的框架源码。

gSOAP工具可以在Windows、Linux和Macosx操作系统下运行,gSOAP工具包中自带有Windows和Macosx操作系统的wsdl2h和soapcpp2可执行文件,而Linux操作系统的,得自己编译。

通过实验证实,用Windows和Linux工具生成的框架代码,是一样样的,没有区别。

如何使用gSOAP,在gSOAP官网,或者在工具包gsoap\doc\soapdoc2.pdf文档中都有很详细的说明,大家可以参考。下面我们通过「国内手机号码归属地查询」的例子,来演示如何使用gSOAP工具。

5. gSOAP演练实例:国内手机号码归属地查询

「国内手机号码归属地查询」免费WEB服务:

WEB服务地址: http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx
WSDL: http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx?wsdl
  1. 下载gSOAP工具,我的版本是「gsoap_2.8.45」。
  2. 创建一个文件夹MobileCode,从gSOAP工具中拷贝如下文件和文件夹到MobileCode文件夹中,

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

    最终效果如下:


    图3

  3. 启动cmd.exe,确保当前路径在刚才创建的MobileCode目录下:


    图4

  4. 使用wsdl2h工具,根据WSDL产生头文件,在cmd中执行以下命令:

    wsdl2h.exe -o mobilecode.h -c -s -t typemap.dat http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx?wsdl
    

    其中-c为产生纯c代码,默认生成 c++代码;-s为不使用STL库,-t为typemap.dat的标识。详情可通过wsdl2h.exe -help查看帮助。

    这里的WSDL文件,可以在wsdl2h命令中在线下载,也可以先下载到本地,然后引用本地WSDL文件,我这里是采用在线下载方式。

  5. 使用soapcpp2工具,根据头文件产生框架代码,在cmd中执行以下命令:

    soapcpp2.exe -2 -C -c -x -Iimport -Icustom mobilecode.h
    

    -2为生成SOAP 1.2版本的代码,-C为仅生成客户端的代码(服务端的不要),-c生成C语言代码,详情可使用soapcpp2.exe -help查看帮助。

  6. 自动生成的源码文件如下图所示,


    图5

    其中custom、import、wsdl2h.exe、soapcpp2.exe、typemap.dat、mobilecode.h、soapClientLib.c这些文件已经没用了,可以删掉,最终剩下的文件只有:


    图6

    在soapStub.h文件中,列出了「国内手机号码归属地查询」WEB服务的所有接口(Client-Side Call Stub Functions),我们的应用程序通过调用这些接口就成了,至于SOAP协议整个过程怎么实现的,都在soapC.c和soapClient.c中,有兴趣的可以去研究,没兴趣的就不管它了,懂得调用以下这几个接口就可以了。


    图7

  7. 接下来,写个main.c,通过soap_call___ns1__getMobileCodeInfo接口来查询国内手机号码归属地信息,并将其打印出来,源码如下所示(实例代码已上传网络:点击下载)。

        #include <stdio.h>
        #include <stdlib.h>
        #include <string.h>
        #include "soapStub.h"
        #include "MobileCodeWSSoap.nsmap"
    
        void getMobileCodeInfo(char *mobileCode)
        {
            struct soap *soap = NULL;
            const char  *endpoint = "http://ws.webxml.com.cn/WebServices/MobileCodeWS.asmx";
            struct _ns1__getMobileCodeInfo          req;
            struct _ns1__getMobileCodeInfoResponse  resp;
    
            soap = soap_new();                                                          // allocate and initalize a context
    
            soap_set_mode(soap, SOAP_C_UTFSTRING);                                      // support multibyte string(for Chinese)
    
            memset(&req, 0x00, sizeof(req));
            req.mobileCode = mobileCode;
            req.userID     = NULL;
    
            if(SOAP_OK == soap_call___ns1__getMobileCodeInfo(soap, endpoint, NULL, &req, &resp)) {
                if (NULL != resp.getMobileCodeInfoResult) {
                    printf("%s\n", resp.getMobileCodeInfoResult);
                }
            }
    
            soap_destroy(soap);                                                         // delete deserialized objects
            soap_end(soap);                                                             // delete allocated data
            soap_free(soap);                                                            // free the soap struct context data
        }
    
        int main(int argc, char **argv)
        {
            if (argc < 2) {
                return 0;
            }
            getMobileCodeInfo(argv[1]);
    
            return 0;
        }

    第一次执行,如下图所示,会出现乱码:


    图8

    这是由于WEB服务应答的归属地信息中包含有UTF-8格式的中文导致的。SOAP协议采用HTTP传输协议+XML数据格式,规定XML字符编码格式必须是UTF-8。为了解决这个问题:

    一、在源码中加入soap_set_mode(soap, SOAP_C_UTFSTRING)语句,告知gSOAP底层代码,我们上层传入的字符编码格式已经是UTF-8,,内部就不参与转码的过程,WEB服务器应答的UTF-8字符也都直接传给上层,此时我们的main.c代码收到的应答也是UTF-8格式的数据。

    二、cmd.exe环境默认的环境是「简体中文GBK」,通过chcp命令就能查到,「活动代码页936」代表的就是「简体中文GBK」,在这种环境下打印UTF-8中文字符当然会乱码,使用命令chcp 65001将控制台的字符集改为UTF-8,「活动代码页65001」代表的就是UTF-8,如此就不会乱码了。


    图9

    乱码问题,这个例子还算是简单的,仅仅是服务器应答的时候带有UTF-8格式的中文字符,从控制台输入的字符(手机号码)是纯数字的,没有涉及到UTF-8编码问题。如果输入也带有中文,那情况会更复杂,有关这方面的详细情况,可参考我博客中此前写的一篇文章「浅谈C/C++编程中的字符编码转换」。

6. gSOAP演练实例:计算器

gSOAP官网有提供gSOAP演练实例「Example XML SOAP calculator client (C)」,有兴趣的也可以去官网学习下。

7. 总结

对本文做个总结:

  1. 开发基于SOAP方式的Web Services,不需要自己实现代码框架,有诸如gSOAP、Apache CXF这样的工具会帮我们实现。


    图10

  2. 以「国内手机号码归属地查询」为例,重点介绍了gSOAP工具转换原理,及其使用方法。

  3. 还遇到了SOAP协议中UTF-8中文字符打印到控制台会乱码的问题,并给出了解决方法。
  • 60
    点赞
  • 56
    收藏
    觉得还不错? 一键收藏
  • 41
    评论
ONVIF协议是一种开放的网络视频接口标准,旨在实现网络摄像机网络视频录像机和其他相关设备的互通互联。在开发ONVIF协议网络摄像机客户端程序时,我们需要遵循以下步骤: 首先,为了开发ONVIF协议网络摄像机客户端程序,我们需要对ONVIF协议进行深入了解。ONVIF协议定义了网络摄像机和客户端之间的通信规则和接口,包括设备发现、视频流传输、设备控制等。我们需要熟悉协议的各个方面,包括消息结构、命令和响应等。 其次,我们需要选择合适的开发平台和工具。ONVIF协议可以在不同平台上运行,如Windows、Linux等。我们可以选择适合我们的开发环境的编程语言和工具,并研究它们的ONVIF协议支持。 接下来,我们需要编写客户端程序代码。首先,我们需要实现设备发现功能,通过发送协议指定的消息,搜索网络中的ONVIF设备。一旦找到设备,我们就可以获取设备的信息,如设备地址、设备型号等。然后,我们可以向设备发送命令,如实时视频流请求、设备时间同步等。我们需要处理设备返回的响应消息,并根据协议规范处理各种结果。 最后,我们需要对开发客户端程序进行测试和调试。我们可以创建模拟的ONVIF设备,模拟设备的各种行为,并验证客户端程序的功能和性能。我们还可以使用一些专业的测试工具来检查客户端程序的兼容性和稳定性。 总而言之,在开发ONVIF协议网络摄像机客户端程序时,我们需要深入了解ONVIF协议,选择适合的开发平台和工具,编写代码实现协议的各种功能,并进行测试和调试。这个过程中需要耐心和细心,以确保开发出高质量的客户端程序

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 41
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值