|
Posted on 2010-08-14 23:46 roy 阅读(2247) 评论(0) 编辑 收藏 引用 所属分类: C/C++
- 电信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; }
-
值得注意的是,如果项目中存在多个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
-
- 成功!
-
|