- 电信provisioning系统中,常常需要与远程服务器实时交换一些数据,以完成用户的请求。由于简单对象访问协议(Simple Object Access Protocol, SOAP)的流行,许多涉及到第三方的应用,我们一般都比较乐意使用SOAP来开发。不过,由于可能涉及到公司的机密,本系列教程的开发实例尽量采用在网上已经公开的Web Service资源。
- gSOAP是一套开源的C/C++软件工具包,使用它能够很方便地开发SOAP网页服务和基于XML的应用程序,就像JAVA里面的axis。
- 首先,我们需要从以下地址下载最新版本的gSOAP 2.7.17:
- https://sourceforge.net/projects/gsoap2/files/
- 其次,gSOAP依赖于Bison和Flex,编译gSOAP的时候会用到,如果没有,从这里下载:
- Bison: http://www.gnu.org/software/bison/
- Flex: http://flex.sourceforge.net/
- 关于这两个工具包的安装步骤可以参考最新的LFS手册:
- http://www.linuxfromscratch.org/lfs/view/6.4/chapter06/bison.html
- http://www.linuxfromscratch.org/lfs/view/6.4/chapter06/flex.html
- 如果不是root用户,没有安装权限的话,可以在configure的时候使用--prefix=/path/to/your/own/directory,指定安装路径。装好之后,修改用户目录的.profile文件,更改PATH和LD_LIBRARY_PATH环境变量,使得系统能够正确搜索到你安装后的可执行文件和库文件即可。
- 这两步准备工作完成后,我们就可以开始编译gSOAP。Linux下编译安装源代码包无非就是tar zxvf xxx,configure,make,make install,由于我不是root用户,没有安装的权限,那么不执行make install也可以使用gSOAP开发程序,只不过使用的时候常常需要指定路径。
- 现在我们的目标是开发一个获取股票信息的客户端程序。服务端采用webxml开发的WSDL,其URL是: http://webservice.webxml.com.cn/WebServices/ChinaStockWebService.asmx?wsdl
- 首先,在gsoap-2.7/gsoap/wsdl/下创建一个stock目录
- -bash-3.2$ mkdir -p stock
- 改变当前路径为stock
- -bash-3.2$ cd stock
- 使用wsdl2h生成stock.h,如果希望生成纯C代码,需要加上-c参数,否则,将会生成C++代码
- -bash-3.2$ ../wsdl2h -c -o stock.h http://webservice.webxml.com.cn/WebServices/ChinaStockWebService.asmx?wsdl
- ** The gSOAP WSDL/Schema processor for C and C++, wsdl2h release 1.2.17
- ** Copyright (C) 2000-2010 Robert van Engelen, Genivia Inc.
- ** All Rights Reserved. This product is provided "as is", without any warranty.
- ** The wsdl2h tool is released under one of the following two licenses:
- ** GPL or the commercial license by Genivia Inc. Use option -l for more info.
- Saving stock.h
- Cannot open file 'typemap.dat'
- Problem reading type map file 'typemap.dat'.
- Using internal type definitions for C instead.
- Connecting to 'http://webservice.webxml.com.cn/WebServices/ChinaStockWebService.asmx?wsdl' to retrieve WSDL/XSD...
- Connected, receiving...
- Done reading 'http://webservice.webxml.com.cn/WebServices/ChinaStockWebService.asmx?wsdl'
- To complete the process, compile with:
- > soapcpp2 stock.h
- 然后,使用soapcpp2生成客户端存根程序和相关的头文件、资源文件,由于我们只开发客户端程序,所以可以指定-C参数
- -bash-3.2$ ../../bin/linux386/soapcpp2 -C stock.h
- ** The gSOAP code generator for C and C++, soapcpp2 release 2.7.17
- ** Copyright (C) 2000-2010, Robert van Engelen, Genivia Inc.
- ** All Rights Reserved. This product is provided "as is", without any warranty.
- ** The soapcpp2 tool is released under one of the following three licenses:
- ** GPL, the gSOAP public license, or the commercial license by Genivia Inc.
- Saving soapStub.h annotated copy of the input declarations
- Saving soapH.h interface declarations
- Saving soapC.c XML serializers
- Saving soapClient.c client calling stubs
- Saving soapClientLib.c client stubs with serializers (use only for libs)
- Using ns2 service name: ChinaStockWebServiceSoap
- Using ns2 service style: document
- Using ns2 service encoding: literal
- Using ns2 service location: http://webservice.webxml.com.cn/WebServices/ChinaStockWebService.asmx
- Using ns2 schema namespace: http://WebXml.com.cn/ChinaStockWebServiceSoap
- Saving ChinaStockWebServiceSoap.getStockImageByCode.req.xml sample SOAP/XML request
- Saving ChinaStockWebServiceSoap.getStockImageByCode.res.xml sample SOAP/XML response
- Saving ChinaStockWebServiceSoap.getStockImageByteByCode.req.xml sample SOAP/XML request
- Saving ChinaStockWebServiceSoap.getStockImageByteByCode.res.xml sample SOAP/XML response
- Saving ChinaStockWebServiceSoap.getStockImage_kByCode.req.xml sample SOAP/XML request
- Saving ChinaStockWebServiceSoap.getStockImage_kByCode.res.xml sample SOAP/XML response
- Saving ChinaStockWebServiceSoap.getStockImage_kByteByCode.req.xml sample SOAP/XML request
- Saving ChinaStockWebServiceSoap.getStockImage_kByteByCode.res.xml sample SOAP/XML response
- Saving ChinaStockWebServiceSoap.getStockInfoByCode.req.xml sample SOAP/XML request
- Saving ChinaStockWebServiceSoap.getStockInfoByCode.res.xml sample SOAP/XML response
- Saving ChinaStockWebServiceSoap.nsmap namespace mapping table
- Using ns3 service name: ChinaStockWebServiceSoap12
- Using ns3 service style: document
- Using ns3 service encoding: literal
- Using ns3 service location: http://webservice.webxml.com.cn/WebServices/ChinaStockWebService.asmx
- Using ns3 schema namespace: http://WebXml.com.cn/ChinaStockWebServiceSoap12
- Saving ChinaStockWebServiceSoap12.getStockImageByCode.req.xml sample SOAP/XML request
- Saving ChinaStockWebServiceSoap12.getStockImageByCode.res.xml sample SOAP/XML response
- Saving ChinaStockWebServiceSoap12.getStockImageByteByCode.req.xml sample SOAP/XML request
- Saving ChinaStockWebServiceSoap12.getStockImageByteByCode.res.xml sample SOAP/XML response
- Saving ChinaStockWebServiceSoap12.getStockImage_kByCode.req.xml sample SOAP/XML request
- Saving ChinaStockWebServiceSoap12.getStockImage_kByCode.res.xml sample SOAP/XML response
- Saving ChinaStockWebServiceSoap12.getStockImage_kByteByCode.req.xml sample SOAP/XML request
- Saving ChinaStockWebServiceSoap12.getStockImage_kByteByCode.res.xml sample SOAP/XML response
- Saving ChinaStockWebServiceSoap12.getStockInfoByCode.req.xml sample SOAP/XML request
- Saving ChinaStockWebServiceSoap12.getStockInfoByCode.res.xml sample SOAP/XML response
- Saving ChinaStockWebServiceSoap12.nsmap namespace mapping table
- Compilation successful
- 接着,就可以利用存根程序提供的接口编写客户端程序了,过程相当简单。
#include
"
soapH.h
"
#include " ChinaStockWebServiceSoap12.nsmap "
int main( int argc, char ** argv) {
if ( argc != 2 ) {
printf( " Usage: %s stock_code\n " , argv[ 0 ]);
exit( - 1 );
}
struct soap soap;
soap_init( & soap);
struct _ns1__getStockInfoByCode request;
struct _ns1__getStockInfoByCodeResponse response;
request.theStockCode = argv[ 1 ];
if ( soap_call___ns3__getStockInfoByCode( & soap, NULL, NULL, & request, & response) == SOAP_OK ) {
int element_counter = response.getStockInfoByCodeResult -> __sizestring;
int i = 0 ;
for ( i = 0 ; i < element_counter; i ++ ) {
switch ( i ) {
case 0 : printf( " Stock code : " ); break ;
case 1 : printf( " Stock name : " ); break ;
case 2 : printf( " Timestamp : " ); break ;
case 3 : printf( " Latest price : " ); break ;
case 4 : printf( " Closing price T-1 : " ); break ;
case 5 : printf( " Opening price : " ); break ;
case 6 : printf( " Ups and downs : " ); break ;
case 7 : printf( " Mininum price : " ); break ;
case 8 : printf( " Maxinum price : " ); break ;
case 9 : printf( " Amount of up/down : " ); break ;
case 10 : printf( " Trading volume : " ); break ;
case 11 : printf( " Trading amount : " ); break ;
case 12 : printf( " Buy price : " ); break ;
case 13 : printf( " Sell price : " ); break ;
case 14 : printf( " Agency trans : " ); break ;
case 15 : printf( " Buy 1 : " ); break ;
case 16 : printf( " Buy 2 : " ); break ;
case 17 : printf( " Buy 3 : " ); break ;
case 18 : printf( " Buy 4 : " ); break ;
case 19 : printf( " Buy 5 : " ); break ;
case 20 : printf( " Sell 1 : " ); break ;
case 21 : printf( " Sell 2 : " ); break ;
case 22 : printf( " Sell 3 : " ); break ;
case 23 : printf( " Sell 4 : " ); break ;
case 24 : printf( " Sell 5 : " ); break ;
default : break ;
}
printf( " %s\n " , response.getStockInfoByCodeResult -> string [i]);
}
}
else {
soap_print_fault( & soap, stderr);
}
soap_destroy( & soap);
soap_end( & soap);
soap_done( & soap);
return 0 ;
}
#include " ChinaStockWebServiceSoap12.nsmap "
int main( int argc, char ** argv) {
if ( argc != 2 ) {
printf( " Usage: %s stock_code\n " , argv[ 0 ]);
exit( - 1 );
}
struct soap soap;
soap_init( & soap);
struct _ns1__getStockInfoByCode request;
struct _ns1__getStockInfoByCodeResponse response;
request.theStockCode = argv[ 1 ];
if ( soap_call___ns3__getStockInfoByCode( & soap, NULL, NULL, & request, & response) == SOAP_OK ) {
int element_counter = response.getStockInfoByCodeResult -> __sizestring;
int i = 0 ;
for ( i = 0 ; i < element_counter; i ++ ) {
switch ( i ) {
case 0 : printf( " Stock code : " ); break ;
case 1 : printf( " Stock name : " ); break ;
case 2 : printf( " Timestamp : " ); break ;
case 3 : printf( " Latest price : " ); break ;
case 4 : printf( " Closing price T-1 : " ); break ;
case 5 : printf( " Opening price : " ); break ;
case 6 : printf( " Ups and downs : " ); break ;
case 7 : printf( " Mininum price : " ); break ;
case 8 : printf( " Maxinum price : " ); break ;
case 9 : printf( " Amount of up/down : " ); break ;
case 10 : printf( " Trading volume : " ); break ;
case 11 : printf( " Trading amount : " ); break ;
case 12 : printf( " Buy price : " ); break ;
case 13 : printf( " Sell price : " ); break ;
case 14 : printf( " Agency trans : " ); break ;
case 15 : printf( " Buy 1 : " ); break ;
case 16 : printf( " Buy 2 : " ); break ;
case 17 : printf( " Buy 3 : " ); break ;
case 18 : printf( " Buy 4 : " ); break ;
case 19 : printf( " Buy 5 : " ); break ;
case 20 : printf( " Sell 1 : " ); break ;
case 21 : printf( " Sell 2 : " ); break ;
case 22 : printf( " Sell 3 : " ); break ;
case 23 : printf( " Sell 4 : " ); break ;
case 24 : printf( " Sell 5 : " ); break ;
default : break ;
}
printf( " %s\n " , response.getStockInfoByCodeResult -> string [i]);
}
}
else {
soap_print_fault( & soap, stderr);
}
soap_destroy( & soap);
soap_end( & soap);
soap_done( & soap);
return 0 ;
}
- 基本上都是套用差不多的格式,不清楚具体参数意义的话,可以参考soapcpp2生成的存根程序及其头文件。把上述代码保存为stock.c,编译命令是:
- gcc -O2 -o stock stock.c soapC.c soapClient.c ../../stdsoap2.c -I../.. -L../.. –lgsoap
- 可以看到,编译时,除了stock.c,还需要包括存根程序soapC.c和soapClient.c,以及gSOAP运行时引擎stdsoap2.c,另外还需要指定头文件搜索路径、库文件搜索路径,以及告诉编译器,链接libgsoap
- 一切正常的话,就大功告成了:
- -bash-3.2$ ./stock sh600000
- Stock code : sh600000
- Stock name : 浦发银行
- Timestamp : 2010-07-08 15:02:07
- Latest price : 13.79
- Closing price T-1 : 13.76
- Opening price : 13.88
- Ups and downs : 0.03
- Mininum price : 13.73
- Maxinum price : 14.06
- Amount of up/down : 0.22%
- Trading volume : 451017.84
- Trading amount : 62602.5809
- Buy price : 13.78
- Sell price : 13.79
- Agency trans : 34.07%
- Buy 1 : 13.78 / 1622.88
- Buy 2 : 13.77 / 687.10
- Buy 3 : 13.76 / 785.00
- Buy 4 : 13.75 / 1430.00
- Buy 5 : 13.74 / 264.00
- Sell 1 : 13.79 / 33.70
- Sell 2 : 13.80 / 64.17
- Sell 3 : 13.81 / 290.80
- Sell 4 : 13.82 / 1318.70
- Sell 5 : 13.83 / 647.70
http://blog.csdn.net/yui/archive/2010/07/08/5721877.aspx