安装
由于本人使用的是 Mac OS 系统,故以 Mac OS 为例说明如何安装 gSOAP。
1)下载 gSOAP
可以在 下载最新版本的 gSOAP。
2)安装 flex, bison, openssl
可以使用brew install
进行安装:
brew install flex bison openssl
3)编译安装 gSOAP
解压上面下载的 gSOAP,然后执行下面的命令:
cd gsoap-2.8./configure --with-openssl=/usr/local/opt/opensslmakesudo make install
安装完成,会出现以下的提示:
安装中如果出现 fatal error: 'openssl/bio.h' file not found
的错误,可以通过尝试重新安装 openssl 和使用最新的 gsoap-2.8 版本的方法来解决,具体解决办法也可以 google 一下。
其他平台的安装教程可以参考官方文档:。
gSOAP 工具
gSOAP 提供了两个工具来方便开发人员使用 C/C++ 语言快速开发Web 服务应用,通过 gSOAP 提供的这两个工具,开发人员可以快速生成服务端与客户端代码框架,接下来开发人员只需要实现具体的接口函数即可。
wsdl2h
wsdl2h 工具根据 WSDL 文件生成 C/C++ .h 头文件。
WSDL(Web Service Description Language)即 Web 服务描述语言,它使用 XML 来对 Web 服务进行描述。 wsdl2h 的用法:wsdl2h -o 头文件名 WSDL文件名或URL
例如:
wsdl2h -o calc.h http://www.genivia.com/calc.wsdl
wsdl2h 根据 URL 指定的 WSDL 生成calc.h
头文件。calc.h
对 Web 服务接口进行定义。
wsdl2h 支持额外的参数:
- -s 生成的头文件不使用 STL
- -o 文件名,指定输出头文件的名称
- -c 产生纯 C 代码,否则是 C++ 代码
- -t 文件名,指定 type map 文件,默认是
typemap.dat
soapcpp2
soapcpp2 工具则从上面生成的头文件生成 SOAP 服务端和客户端框架代码。例如对于上面的cacl.h
,使用 soapcpp2 命令:
soapcpp2 -i -Iimport calc.h
soapcpp2 也支持额外的参数:
- -i 生成 C++ 包装类,客户端为
xxxProxy.h(.cpp)
,服务端为xxxService.h(.cpp)
- -I 指定 import 的路径,比如需要引入
stlvector.h
文件来支持 STL vector 的序列化 - -C 仅生成客户端代码
- -S 仅生成服务端代码
- -c 产生纯 C 代码,否则是 C++ 代码
- -x 不要产生 XML 示例文件
- -L 不要产生
soapClientLib.c
和soapServerLib.c
文件
例子
gSOAP 中包含了大量的例子以便让开发人员快速了解如何使用 gSOAP 开发 Web 服务。
我们以 gSOAP 的 samples 目录下的 calc++ 的代码为例,说明如何使用 gSOAP 来编写客户端和的服务端代码。calc++ 目录已经包含了 calc.h
头文件,这个头文件跟上面我们使用 wsdl2h 生成的 calc.h
头文件并不完全相同,为了实验的方便,我们使用 calc++ 目录的calc.h
头文件进行实验。
calc.h
头文件:
//gsoap ns service method: add Sums two valuesint ns__add(double a, double b, double *result); //gsoap ns service method: sub Subtracts two values int ns__sub(double a, double b, double *result); //gsoap ns service method: mul Multiplies two values int ns__mul(double a, double b, double *result); //gsoap ns service method: div Divides two values int ns__div(double a, double b, double *result); //gsoap ns service method: pow Raises a to b int ns__pow(double a, double b, double *result);
然后,我们使用 soapcpp2 工具来生成客户端和服务端的框架代码:
soapcpp2 -i calc.h
客户端代码
calcclient.c++
代码:
#include "soapcalcProxy.h"#include "calc.nsmap"const char server[] = "http://127.0.0.1:8080"; int main(int argc, char **argv) { if (argc < 4) { fprintf(stderr, "Usage: [add|sub|mul|div|pow] num num\n"); exit(0); } double a, b, result; a = strtod(argv[2], NULL); b = strtod(argv[3], NULL); calcProxy calc; calc.soap_endpoint = server; switch (*argv[1]) { case 'a': calc.add(a, b, &result); break; case 's': calc.sub(a, b, &result); break; case 'm': calc.mul(a, b, &result); break; case 'd': calc.div(a, b, &result); break; case 'p': calc.pow(a, b, &result); break; default: fprintf(stderr, "Unknown command\n"); exit(0); } if (calc.error) calc.soap_stream_fault(std::cerr); else printf("result = %g\n", result); return 0; }
由于代码使用 STL,为了顺利编译通过,需要将 gSOAP 中的stdsoap2.cpp
和stdsoap2.h
文件拷贝到客户端和服务端代码所在的目录。
g++ -o calcclient++ calcclient.cpp soapC.cpp soapcalcProxy.cpp stdsoap2.cpp
编译顺利通过。
服务端代码
calcserver.cpp
代码如下,其中可以指定服务端的端口号:
#include "soapcalcService.h"#include "calc.nsmap"int main(int argc, char **argv) { calcService calc; if (argc < 2) calc.serve(); /* serve as CGI application */ else { int port = atoi(argv[1]); if (!port) { fprintf(stderr, "Usage: calcserver++\n"); exit(0); } /* run iterative server on port until fatal error */ if (calc.run(port)) { calc.soap_stream_fault(std::cerr); exit(-1); } } return 0; } int calcService::add(double a, double b, double *result) { *result = a + b; return SOAP_OK; } int calcService::sub(double a, double b, double *result) { *result = a - b; return SOAP_OK; } int calcService::mul(double a, double b, double *result) { *result = a * b; return SOAP_OK; } int calcService::div(double a, double b, double *result) { if (b) *result = a / b; else { char *s = (char*)soap_malloc(this, 1024); (SOAP_SNPRINTF(s, 1024, 100), " Can't divide %f by %f ", a, b); return soap_senderfault("Division by zero", s); } return SOAP_OK; } int calcService::pow(double a, double b, double *result) { *result = ::pow(a, b); if (soap_errno == EDOM) /* soap_errno is like errno, but compatible with Win32 */ { char *s = (char*)soap_malloc(this, 1024); (SOAP_SNPRINTF(s, 1024, 100), "Can't take power of %f to %f ", a, b); return soap_senderfault("Power function domain error", s); } return SOAP_OK; }
然后使用 g++ 来对服务端代码进行编译:
g++ -o calcserver++ calcserver.cpp soapC.cpp soapcalcService.cpp stdsoap2.cpp
编译同样顺利通过。
测试
运行上面编译好的calcserver
和calcclient
可执行文件
转自:https://blog.csdn.net/lihao21/article/details/70168050