- 电信provisioning系统中,常常需要与远程服务器实时交换一些数据,以完成用户的请求。由于简单对象访问协议(Simple Object Access Protocol, SOAP)的流行,许多涉及到第三方的应用,我们一般都比较乐意使用SOAP来开发。不过,由于可能涉及到公司的机密,本系列教程的开发实例尽量采用在网上已经公开的Web Service资源。
- 上文已经交待了gSOAP在Linux环境下的编译方法和客户端的实例程序,本文继续讲解其服务端程序的开发。由于不可能获得真正的数据库内容,我们设定的目标是,所有返回的内容都是客户端传入的股票代码。
- 首先,在gsoap-2.7/gsoap/wsdl/下创建一个stock_server目录
- -bash-3.2$ mkdir -p stock_server
- 改变当前路径为stock_server
- -bash-3.2$ cd stock_server
- 仍然使用wsdl2h生成基于纯C代码的stock.h
- -bash-3.2$ ../wsdl2h -c -o stock.h http://webservice.webxml.com.cn/WebServices/ChinaStockWebService.asmx?wsdl
- 然后,生成服务端存根程序,并且不生成xml文件和soapServerLib.c
- -bash-3.2$ ../../bin/linux386/soapcpp2 -S -L -x 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 soapServer.c server request dispatcher
- 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.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.nsmap namespace mapping table
- Compilation successful
- 服务端的主程序稍微比客户端复杂些,因为还要处理客户端的其他请求,至少要有其函数体,否则编译时会报错。
#include
"
soapH.h
"
#include " ChinaStockWebServiceSoap12.nsmap "
int main( int argc, char ** argv) {
if ( argc != 2 ) {
printf( " Usage: %s port\n " , argv[ 0 ]);
exit( - 1 );
}
int port = atol(argv[ 1 ]);
struct soap soap;
soap_init( & soap);
int m, s;
if ( (m = soap_bind( & soap, NULL, port, 100 )) < 0 ) {
soap_print_fault( & soap, stderr);
}
else {
printf( " Socket connect successfully: master socket = %d\n " , m);
int i = 0 ;
while ( 1 ) {
if ( (s = soap_accept( & soap)) < 0 ) {
soap_print_fault( & soap, stderr);
break ;
}
printf( " Connection %d accepted from IP = %d.%d.%d.%d, slave socket = %d\n " , ++ i, (soap.ip >> 24 ) & 0xff , (soap.ip >> 16 ) & 0xff , (soap.ip >> 8 ) & 0xff , soap.ip & 0xff , s);
if ( soap_serve( & soap) != SOAP_OK ) {
soap_print_fault( & soap, stderr);
break ;
}
soap_end( & soap);
}
}
soap_done( & soap);
}
int __ns3__getStockInfoByCode(
struct soap * soap,
struct _ns1__getStockInfoByCode * request,
struct _ns1__getStockInfoByCodeResponse * response) {
int element_counter = 25 ;
response -> getStockInfoByCodeResult = ( struct ns1__ArrayOfString * ) malloc( sizeof ( struct ns1__ArrayOfString));
response -> getStockInfoByCodeResult -> __sizestring = element_counter;
response -> getStockInfoByCodeResult -> string = ( char ** ) malloc( sizeof ( char * ) * element_counter);
int i = 0 ;
for ( i = 0 ; i < element_counter; i ++ ) {
response -> getStockInfoByCodeResult -> string [i] = ( char * ) malloc( sizeof ( char ) * 32 );
strcpy(response -> getStockInfoByCodeResult -> string [i], request -> theStockCode);
}
return SOAP_OK;
}
int __ns3__getStockImage_USCOREkByteByCode(
struct soap * soap,
struct _ns1__getStockImage_USCOREkByteByCode * request,
struct _ns1__getStockImage_USCOREkByteByCodeResponse * response) {
return SOAP_OK;
}
int __ns3__getStockImage_USCOREkByCode(
struct soap * soap,
struct _ns1__getStockImage_USCOREkByCode * request,
struct _ns1__getStockImage_USCOREkByCodeResponse * response) {
return SOAP_OK;
}
int __ns3__getStockImageByteByCode(
struct soap * soap,
struct _ns1__getStockImageByteByCode * request,
struct _ns1__getStockImageByteByCodeResponse * response) {
return SOAP_OK;
}
int __ns3__getStockImageByCode(
struct soap * soap,
struct _ns1__getStockImageByCode * request,
struct _ns1__getStockImageByCodeResponse * response) {
return SOAP_OK;
}
int __ns2__getStockInfoByCode(
struct soap * soap,
struct _ns1__getStockInfoByCode * request,
struct _ns1__getStockInfoByCodeResponse * response) {
int element_counter = 25 ;
response -> getStockInfoByCodeResult = ( struct ns1__ArrayOfString * ) malloc( sizeof ( struct ns1__ArrayOfString));
response -> getStockInfoByCodeResult -> __sizestring = element_counter;
response -> getStockInfoByCodeResult -> string = ( char ** ) malloc( sizeof ( char * ) * element_counter);
int i = 0 ;
for ( i = 0 ; i < element_counter; i ++ ) {
response -> getStockInfoByCodeResult -> string [i] = ( char * ) malloc( sizeof ( char ) * 32 );
strcpy(response -> getStockInfoByCodeResult -> string [i], request -> theStockCode);
}
return SOAP_OK;
}
int __ns2__getStockImage_USCOREkByteByCode(
struct soap * soap,
struct _ns1__getStockImage_USCOREkByteByCode * request,
struct _ns1__getStockImage_USCOREkByteByCodeResponse * response) {
return SOAP_OK;
}
int __ns2__getStockImage_USCOREkByCode(
struct soap * soap,
struct _ns1__getStockImage_USCOREkByCode * request,
struct _ns1__getStockImage_USCOREkByCodeResponse * response) {
return SOAP_OK;
}
int __ns2__getStockImageByteByCode(
struct soap * soap,
struct _ns1__getStockImageByteByCode * request,
struct _ns1__getStockImageByteByCodeResponse * response) {
return SOAP_OK;
}
int __ns2__getStockImageByCode(
struct soap * soap,
struct _ns1__getStockImageByCode * request,
struct _ns1__getStockImageByCodeResponse * response) {
return SOAP_OK;
}
#include " ChinaStockWebServiceSoap12.nsmap "
int main( int argc, char ** argv) {
if ( argc != 2 ) {
printf( " Usage: %s port\n " , argv[ 0 ]);
exit( - 1 );
}
int port = atol(argv[ 1 ]);
struct soap soap;
soap_init( & soap);
int m, s;
if ( (m = soap_bind( & soap, NULL, port, 100 )) < 0 ) {
soap_print_fault( & soap, stderr);
}
else {
printf( " Socket connect successfully: master socket = %d\n " , m);
int i = 0 ;
while ( 1 ) {
if ( (s = soap_accept( & soap)) < 0 ) {
soap_print_fault( & soap, stderr);
break ;
}
printf( " Connection %d accepted from IP = %d.%d.%d.%d, slave socket = %d\n " , ++ i, (soap.ip >> 24 ) & 0xff , (soap.ip >> 16 ) & 0xff , (soap.ip >> 8 ) & 0xff , soap.ip & 0xff , s);
if ( soap_serve( & soap) != SOAP_OK ) {
soap_print_fault( & soap, stderr);
break ;
}
soap_end( & soap);
}
}
soap_done( & soap);
}
int __ns3__getStockInfoByCode(
struct soap * soap,
struct _ns1__getStockInfoByCode * request,
struct _ns1__getStockInfoByCodeResponse * response) {
int element_counter = 25 ;
response -> getStockInfoByCodeResult = ( struct ns1__ArrayOfString * ) malloc( sizeof ( struct ns1__ArrayOfString));
response -> getStockInfoByCodeResult -> __sizestring = element_counter;
response -> getStockInfoByCodeResult -> string = ( char ** ) malloc( sizeof ( char * ) * element_counter);
int i = 0 ;
for ( i = 0 ; i < element_counter; i ++ ) {
response -> getStockInfoByCodeResult -> string [i] = ( char * ) malloc( sizeof ( char ) * 32 );
strcpy(response -> getStockInfoByCodeResult -> string [i], request -> theStockCode);
}
return SOAP_OK;
}
int __ns3__getStockImage_USCOREkByteByCode(
struct soap * soap,
struct _ns1__getStockImage_USCOREkByteByCode * request,
struct _ns1__getStockImage_USCOREkByteByCodeResponse * response) {
return SOAP_OK;
}
int __ns3__getStockImage_USCOREkByCode(
struct soap * soap,
struct _ns1__getStockImage_USCOREkByCode * request,
struct _ns1__getStockImage_USCOREkByCodeResponse * response) {
return SOAP_OK;
}
int __ns3__getStockImageByteByCode(
struct soap * soap,
struct _ns1__getStockImageByteByCode * request,
struct _ns1__getStockImageByteByCodeResponse * response) {
return SOAP_OK;
}
int __ns3__getStockImageByCode(
struct soap * soap,
struct _ns1__getStockImageByCode * request,
struct _ns1__getStockImageByCodeResponse * response) {
return SOAP_OK;
}
int __ns2__getStockInfoByCode(
struct soap * soap,
struct _ns1__getStockInfoByCode * request,
struct _ns1__getStockInfoByCodeResponse * response) {
int element_counter = 25 ;
response -> getStockInfoByCodeResult = ( struct ns1__ArrayOfString * ) malloc( sizeof ( struct ns1__ArrayOfString));
response -> getStockInfoByCodeResult -> __sizestring = element_counter;
response -> getStockInfoByCodeResult -> string = ( char ** ) malloc( sizeof ( char * ) * element_counter);
int i = 0 ;
for ( i = 0 ; i < element_counter; i ++ ) {
response -> getStockInfoByCodeResult -> string [i] = ( char * ) malloc( sizeof ( char ) * 32 );
strcpy(response -> getStockInfoByCodeResult -> string [i], request -> theStockCode);
}
return SOAP_OK;
}
int __ns2__getStockImage_USCOREkByteByCode(
struct soap * soap,
struct _ns1__getStockImage_USCOREkByteByCode * request,
struct _ns1__getStockImage_USCOREkByteByCodeResponse * response) {
return SOAP_OK;
}
int __ns2__getStockImage_USCOREkByCode(
struct soap * soap,
struct _ns1__getStockImage_USCOREkByCode * request,
struct _ns1__getStockImage_USCOREkByCodeResponse * response) {
return SOAP_OK;
}
int __ns2__getStockImageByteByCode(
struct soap * soap,
struct _ns1__getStockImageByteByCode * request,
struct _ns1__getStockImageByteByCodeResponse * response) {
return SOAP_OK;
}
int __ns2__getStockImageByCode(
struct soap * soap,
struct _ns1__getStockImageByCode * request,
struct _ns1__getStockImageByCodeResponse * response) {
return SOAP_OK;
}
-
值得注意的是,如果项目中存在多个name space,最好把全部name space的相关方法都进行编码,否则可能出现意想不到的错误:客户端明明是调用ns3的方法,但是服务端却使用了ns2的方法来提供服务。这一点我也比较费解,可能与wsdl本身的写法有关。
上述服务端程序的编译命令是
gcc -O2 -o stock_server stock_server.c soapC.c soapServer.c ../../stdsoap2.c -I../.. -L../.. -lgsoap
同时,要把上文的客户端程序修改一下,支持指定的end point,不指定end point再取默认的end point
#include " soapH.h "
#include " ChinaStockWebServiceSoap12.nsmap "
int main( int argc, char ** argv) {
if ( argc != 2 && argc != 3 ) {
printf( " Usage: %s stock_code [end_point]\n " , argv[ 0 ]);
exit( - 1 );
}
struct soap soap;
soap_init( & soap);
soap_set_mode( & soap, SOAP_C_UTFSTRING);
struct _ns1__getStockInfoByCode request;
struct _ns1__getStockInfoByCodeResponse response;
request.theStockCode = argv[ 1 ];
char * endpoint = NULL;
if ( argc == 3 )
endpoint = argv[ 2 ];
if ( soap_call___ns3__getStockInfoByCode( & soap, endpoint, 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 ;
}
- 使服务端程序在某一高位端口下运行,比如
- -bash-3.2$ ./stock_server 6883
- Socket connect successfully: master socket = 3
- 另起一个窗口执行客户端程序,并且指定 end point
- -bash-3.2$ ./stock sh600000 http://localhost:6883
- Stock code : sh600000
- Stock name : sh600000
- Timestamp : sh600000
- Latest price : sh600000
- Closing price T-1 : sh600000
- Opening price : sh600000
- Ups and downs : sh600000
- Mininum price : sh600000
- Maxinum price : sh600000
- Amount of up/down : sh600000
- Trading volume : sh600000
- Trading amount : sh600000
- Buy price : sh600000
- Sell price : sh600000
- Agency trans : sh600000
- Buy 1 : sh600000
- Buy 2 : sh600000
- Buy 3 : sh600000
- Buy 4 : sh600000
- Buy 5 : sh600000
- Sell 1 : sh600000
- Sell 2 : sh600000
- Sell 3 : sh600000
- Sell 4 : sh600000
- Sell 5 : sh600000
- 成功!
-