用 gSOAP 实现 Web Service 的简单例子
系统环境:Centos 6.3 操作系统,gsoap-2.8。
1. Web Service
Web Service就是为应用程序提供的一个网络接口。客户端发送数据,服务端获取数据并进行处理,然后将结果返回给客户端,从而达到交互和分布式处理的效果,与平台和开发语言无关。
2. WSDL文件
WSDL文件提供了一种对函数、函数参数及返回值描述的标准的XML文件。WSDL简化了开发流程,只要从服务提供商处获得相应接口的WSDL文件,就可以通过该文件利用软件自动生成客户端不同语言的代码。
3. 示例程序
这里借用互联网上的一个例子,客户端输入两个数字,服务端提供加法运算服务并将结果返回给客户端。
4. 拷贝所需文件
将 gsoap 源码包中的 stdsoap2.h 和 stdsoap2.c 文件拷贝到工作目录。
5. 定义函数声明文件 add.h
//gsoap ns2 service name: add
int ns2__add( int num1, int num2, int* sum );
因为这个例子简单,不需要用wsdl2h命令和WSDL文件生成头文件,所以直接手动定义了这个头文件,后面有详细介绍。
6. 执行 soapcpp2 命令生成远程调用需要的文件。
# soapcpp2 -c add.h
7. 创建服务端程序 addserver.c
#include "soapH.h"
#include "add.nsmap"
int main(int argc, char **argv)
{
int m, s;
struct soap add_soap;
soap_init(&add_soap);
soap_set_namespaces(&add_soap, namespaces);
if (argc < 2)
{
printf("usage: %s <server_port> \n", argv[0]);
exit(1);
}else
{
m = soap_bind(&add_soap, NULL, atoi(argv[1]), 100);
if (m < 0)
{
soap_print_fault(&add_soap, stderr);
exit(-1);
}
fprintf(stderr, "Socket connection successful: master socket = %d\n", m);
for (;;)
{
s = soap_accept(&add_soap);
if (s < 0)
{
soap_print_fault(&add_soap, stderr);
exit(-1);
}
fprintf(stderr, "Socket connection successful: slave socket = %d\n", s);
soap_serve(&add_soap);
soap_end(&add_soap);
}
}
return 0;
}
int ns2__add(struct soap *add_soap, int num1, int num2, int *sum)
{
*sum = num1 + num2;
return 0;
}
8. 创建客户端程序 addclient.c
#include "soapStub.h"
#include "add.nsmap"
int add(const char *server, int num1, int num2, int *sum)
{
struct soap add_soap;
int result = 0;
soap_init(&add_soap);
soap_set_namespaces(&add_soap, namespaces);
soap_call_ns2__add(&add_soap, server, NULL, num1, num2, sum);
printf("server is %s, num1 is %d, num2 is %d\n", server, num1, num2);
if (add_soap.error)
{
printf("soap error: %d, %s, %s\n", add_soap.error, *soap_faultcode(&add_soap), *soap_faultstring(&add_soap));
result = add_soap.error;
}
soap_end(&add_soap);
soap_done(&add_soap);
return result;
}
9. 创建测试程序 addtest.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int add(const char *server, int num1, int num2, int *sum);
int main(int argc, char **argv)
{
int result = -1;
char server[128] = {0};
int num1;
int num2;
int sum;
if (argc < 4)
{
printf("usage: %s <ip:port> num1 num2 \n", argv[0]);
exit(1);
}
strcpy(server,argv[1]);
num1 = atoi(argv[2]);
num2 = atoi(argv[3]);
result = add(server, num1, num2, &sum);
if (result != 0)
{
printf("soap error, errcode=%d\n", result);
}else
{
printf("%d + %d = %d\n", num1, num2, sum);
}
return 0;
}
10. 编译程序
# gcc -o addserver addserver.c soapH.h stdsoap2.h stdsoap2.c soapServer.c soapC.c
# gcc -o addclient addclient.c soapH.h stdsoap2.h stdsoap2.c soapClient.c soapC.c addtest.c
11. 运行程序
运行服务端程序:
# ./addserver 7788
Socket connection successful: master socket = 3
运行客户端程序:
# ./addclient 127.0.0.1:7788 3 5
server is 127.0.0.1:7788, num1 is 3, num2 is 5
3 + 5 = 8
这就完成了一个简单的gSOAP应用示例。
因为这个例子简单,没用WSDL文件,如果需要WSDL文件,就应该按下面步骤生成和解析头文件:
1. 先用 wsdl2h 命令生成生成C/C++头文件
格式: wsdl2h -c -o <输出文件名>.h <服务器端的Web地址>?wsdl。例如:
# wsdl2h -c -o test.h http://cqf.amobile.cn/submitdata/service.asmx?wsdl
如果使用了-s参数,表示不使用STL。
2. 然后再使用 soapcpp2 命令解析 test.h 文件,生成存根程序。
# soapcpp2 -c -C test.h
命令中参数-c代表生成标准C程序,若没有这个参数,则生成C++程序。
命令中参数-C代表仅生成客户端程序,若没有这个参数,则默认生成客户端和服务端程序。