1. 专栏导读
本专栏第一篇文章「专栏开篇」列出了专栏的完整目录,按目录顺序阅读,有助于你的理解,专栏前面文章讲过的知识点(或代码段),后面文章不会赘述。为了节省篇幅,突出重点,在文章中展示的示例代码仅仅是关键代码,你可以在「专栏开篇」中获取完整代码。
如有错误,欢迎你的留言纠正!让我们共同成长!你的「点赞」或「打赏」是对我最大的支持和鼓励!
2. 不要自己造轮子
ONVIF标准是使用SOAP方式实现的Web Services,本专栏上一篇文章已经介绍了什么是Web Services,涉及很多概念,包括SOAP、HTTP、XML,RPC等等。辣么多东东,全部要自己码代码实现吗?当然不用,我们不必自己造轮子,有现成的工具会帮我们自动生产大部分的代码框架。
这样的工具有很多,比如:
- gSOAP工具,适用于C/C++语言开发。
- 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到底会自动生成哪些框架代码,下图中浅绿色框中的部分就是自动生成的代码。
4. gSOAP工具转换原理
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
- 下载gSOAP工具,我的版本是「gsoap_2.8.45」。
-
创建一个文件夹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\
最终效果如下:
-
启动cmd.exe,确保当前路径在刚才创建的MobileCode目录下:
-
使用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文件,我这里是采用在线下载方式。
-
使用soapcpp2工具,根据头文件产生框架代码,在cmd中执行以下命令:
soapcpp2.exe -2 -C -c -x -Iimport -Icustom mobilecode.h
-2为生成SOAP 1.2版本的代码,-C为仅生成客户端的代码(服务端的不要),-c生成C语言代码,详情可使用soapcpp2.exe -help查看帮助。
-
自动生成的源码文件如下图所示,
其中custom、import、wsdl2h.exe、soapcpp2.exe、typemap.dat、mobilecode.h、soapClientLib.c这些文件已经没用了,可以删掉,最终剩下的文件只有:
在soapStub.h文件中,列出了「国内手机号码归属地查询」WEB服务的所有接口(Client-Side Call Stub Functions),我们的应用程序通过调用这些接口就成了,至于SOAP协议整个过程怎么实现的,都在soapC.c和soapClient.c中,有兴趣的可以去研究,没兴趣的就不管它了,懂得调用以下这几个接口就可以了。
-
接下来,写个main.c,通过soap_call___ns1__getMobileCodeInfo接口来查询国内手机号码归属地信息,并将其打印出来,源码如下所示(实例代码已上传网络:点击下载)。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
第一次执行,如下图所示,会出现乱码:
这是由于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,如此就不会乱码了。
乱码问题,这个例子还算是简单的,仅仅是服务器应答的时候带有UTF-8格式的中文字符,从控制台输入的字符(手机号码)是纯数字的,没有涉及到UTF-8编码问题。如果输入也带有中文,那情况会更复杂,有关这方面的详细情况,可参考我博客中此前写的一篇文章「浅谈C/C++编程中的字符编码转换」。
6. gSOAP演练实例:计算器
gSOAP官网有提供gSOAP演练实例「Example XML SOAP calculator client (C)」,有兴趣的也可以去官网学习下。
7. 总结
对本文做个总结:
-
开发基于SOAP方式的Web Services,不需要自己实现代码框架,有诸如gSOAP、Apache CXF这样的工具会帮我们实现。
-
以「国内手机号码归属地查询」为例,重点介绍了gSOAP工具转换原理,及其使用方法。
- 还遇到了SOAP协议中UTF-8中文字符打印到控制台会乱码的问题,并给出了解决方法。