服务咨询热线:

022-88711099

当前位置:

使用gSOAP开发实例(1) 股票信息客户端程序

发布时间:2011/11/19 14:02 作者:夜风冷 访问量:1608

使用gSOAP开发实例(1) 股票信息客户端程序

原文载于CSDN(http://blog.csdn.net/yui/article/details/5721877

电信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;
}

基本上都是套用差不多的格式,不清楚具体参数意义的话,可以参考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