工具包地址:http://gsoap2.sourceforge.net/
原理:请自行了解wsdl、webService、soap
soap简单介绍http://www.runoob.com/soap/soap-tutorial.html
wsdl简单介绍http://www.runoob.com/wsdl/wsdl-tutorial.html
webService简单介绍http://www.runoob.com/webservices/webservices-tutorial.html
毕竟是简单介绍,了解基本信息即可
我下载的gsoap版本是2.8,所以exe工具目录是gsoap-2.8\gsoap\bin\win32,win32目录中是可执行文件包括soapcpp2.exe和wsdl2h.exe,
wsdl2h用作wsdl和.h文件的转换。
soapcpp2用头文件生成客户端/服务端等开发需要的h和cpp文件,也可以生成wsdl文件
此处直接使用gsoap2.8中自带的sample演示。目录为gsoap-2.8\gsoap\samples\calc。gsoap-2.8\gsoap\samples中有很多实例,网上多疑calc为例,本文也是。
(cd 到gsoapcpp2和wsdl2h所在目录)
服务端:
1.生成服务端必要文件
soapcpp2.exe -S -i ..\..\samples\calc\calc.h
-S表示生成服务端文件
-i表示从SOAP结构生成服务代理和继承的对象
这里win32目录下会生成很多xml文件、cpp文件、h文件,还有wsdl文件、nsmap文件、xsd文件,可以通过-d参数指定路径,以免管理混乱,还可以拒绝xml文件的生成
请先手动在win32目录下创建calcServer目录
soapcpp2.exe -S -i -x ..\..\samples\calc\calc.h -d .\calcServer
-x表示不生成xml文件,结果如下
2.新建工程
不赘述
main.cpp代码如下
#include "soapcalcService.h"
#include "calc.nsmap"
#include <math.h>
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++ <port>\n");
exit(0);
}
/* run iterative server on port untilfatal error */
if (calc.run(port))
{
calc.soap_stream_fault(std::cerr);
exit(-1);
}
}
return 0;
}
/** Auto-test server operation ns__add */
int calcService::add(double a, double b, double *result)
{ /* Echo request-response parameter */
*result = a + b;
return SOAP_OK;
}
/** Auto-test server operation ns__sub */
int calcService::sub(double a, double b, double *result)
{ /* Echo request-response parameter */
*result = a - b;
return SOAP_OK;
}
/** Auto-test server operation ns__mul */
int calcService::mul(double a, double b, double *result)
{ /* Echo request-response parameter */
*result = a * b;
return SOAP_OK;
}
/** Auto-test server operation ns__div */
int calcService::div(double a, double b, double *result)
{ /* Echo request-response parameter */
*result = a / b;
return SOAP_OK;
}
/** Auto-test server operation ns__pow */
int calcService::pow(double a, double b, double *result)
{ /* Echo request-response parameter */
*result = ::pow(a, b);
return SOAP_OK;
}
需要自己实现h文件中定义的4个接口。可以理解为:h文件里面声明了,总得自己实现吧。可以参考gsoap-2.8\gsoap\samples\calc中calcserver.cpp的实现。只有头文件和参考的cpp文件的情况下,自己不实现,没人帮你实现。
除了main.cpp文件以外,还需要将生成的
calc.nsmap
soapC.cpp
soapcalcService.cpp
soapcalcService.h
soapH.h
soapStub.h
和gsoap目录下的
stdsoap2.cpp
stdsoap2.h
复制到工程目录下
3.直接编译,测试
编译后,用命令行窗口执行testSoapCalc 8080
然后用浏览器打开http://localhost:8080
看到的是
因为只是打开端口,并没有通信,所以只能看到这些,编译执行客户端程序就能看到效果了
客户端:
1.生成客户端必要文件
soapcpp2.exe -C -i -x ..\..\samples\calc\calc.h -d .\calcClient\
请手动在win32目录下创建calcClient目录
-C表示生成客户端代码
2.新建工程
需要复制的是生成的
calc.nsmap
soapC.cpp
soapcalcProxy.cpp
soapcalcProxy.h
soapH.h
soapStub.h
以及soap目录下的
stdsoap2.cpp
stdsoap2.h
一定要记得stdsoap2.cpp和stdsoap2.h,
一定要记得stdsoap2.cpp和stdsoap2.h,
一定要记得stdsoap2.cpp和stdsoap2.h,
重要的事情说三遍
main.cpp代码如下
#include "soapcalcProxy.h"
#include "calc.h"
#include "calc.nsmap"
const char server[] = "http://localhost: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);
}
其中const char server[] = "http://localhost:8080";指定端口号,端口号可改以服务端设置的端口号为准
3.编译执行
服务端程序要运行起来才能执行客户端程序,虽然都在同一台电脑里面
testSoapCalcClient.exe a 1 2
运算1和2的加法
运算完后服务端不会退出,但是客户端会退出,可继续执行命令
soapCalcProxy.cpp和soapClient.cpp有冲突
-i生成soapCalcProxy.cpp,不会生成soapClient.cpp文件
不要-i则生成soapClient.cpp不生成soapCalcProxy.cpp文件
没有soapClient.cpp也没关系,只要有编译出来的nsmap文件、cpp文件、h文件和soap目录下的stdsoap2.cpp、stdsoap2.h文件就够了