Windows下用gSOAP开发webservice程序

1、介绍

gSOAP编译工具提供了一个SOAP/XML 关于C/C++ 语言的实现,从而让C/C++语言开发web服务或客户端程序的工作变得轻松了很多。gSOAP利用编译器技术提供了一组透明化的SOAP API,并将与开发无关的SOAP实现细节相关的内容对用户隐藏起来。gSOAP的编译器能够自动的将用户定义的本地化的C或C++数据类型转变为符合XML语法的数据结构,反之亦然。

gSOAP包含一个WSDL生成器,用它来为你的web服务生成web服务的解释。gSOAP的解释器及导入器可以使用户不需要分析web服务的细节就可以实现一个客户端或服务端程序。

官网地址:http://www.cs.fsu.edu/~engelen/soap.html

下载地址:http://sourceforge.net/projects/gsoap2/

2、开发过程(以经典的calc为例)

第一步:下载gSOAP Toolkit,在gsoap\bin\win32目录可以看到两个应用:soapcpp2.exe和wsdl2h.exe;

第二步:生成客户端和服务器端框架

需使用gSOAP生成客户端和服务器端代码框架。我们有两种做法:

编写WSDL,使用wsdl2h生成头文件,再soapcpp2生成框架代码;
编写头文件,使用soapcpp2生成框架代码;
方法1比较通用,可方便使用其他语言开发,但是编写wsdl语法复杂;方法2比较简单,但不能与其他语言通用。
我个人会选择第2个方法,效率第一!当然,如果已经从其他地方得到了wsdl文件,就用第1中方法。

方法2可参考:http://blog.csdn.net/kisaa133/article/details/7729856

下面来说方法1:
用wsdl2h生成头文件过程如下:
使用的wsdl为:http://www.genivia.com/calc.wsdl
将 wsdl2h.exe;soapcpp2.exe;typemap.dat;calc.wsdl 拷贝到你自己的工作目录下,将wsdl文件也保存为Calculator.wsdl,在cmd中,将目录切换到工作目录,执行 wsdl2h.exe -p calc.wsdl,将生成calc.h

calc.wsdl 文件如下

<?xml version="1.0" encoding="UTF-8"?>
<definitions name="calc"
 targetNamespace="http://websrv.cs.fsu.edu/~engelen/calc.wsdl"
 xmlns:tns="http://websrv.cs.fsu.edu/~engelen/calc.wsdl"
 xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
 xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
 xmlns:ns="urn:calc"
 xmlns:SOAP="http://schemas.xmlsoap.org/wsdl/soap/"
 xmlns:MIME="http://schemas.xmlsoap.org/wsdl/mime/"
 xmlns:DIME="http://schemas.xmlsoap.org/ws/2002/04/dime/wsdl/"
 xmlns:WSDL="http://schemas.xmlsoap.org/wsdl/"
 xmlns="http://schemas.xmlsoap.org/wsdl/">

<types>

 <schema targetNamespace="urn:calc"
  xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
  xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  xmlns:ns="urn:calc"
  xmlns="http://www.w3.org/2001/XMLSchema"
  elementFormDefault="unqualified"
  attributeFormDefault="unqualified">
  <import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
 </schema>

</types>

<message name="addRequest">
 <part name="a" type="xsd:double"/>
 <part name="b" type="xsd:double"/>
</message>

<message name="addResponse">
 <part name="result" type="xsd:double"/>
</message>

<message name="subRequest">
 <part name="a" type="xsd:double"/>
 <part name="b" type="xsd:double"/>
</message>

<message name="subResponse">
 <part name="result" type="xsd:double"/>
</message>

<message name="mulRequest">
 <part name="a" type="xsd:double"/>
 <part name="b" type="xsd:double"/>
</message>

<message name="mulResponse">
 <part name="result" type="xsd:double"/>
</message>

<message name="divRequest">
 <part name="a" type="xsd:double"/>
 <part name="b" type="xsd:double"/>
</message>

<message name="divResponse">
 <part name="result" type="xsd:double"/>
</message>

<message name="powRequest">
 <part name="a" type="xsd:double"/>
 <part name="b" type="xsd:double"/>
</message>

<message name="powResponse">
 <part name="result" type="xsd:double"/>
</message>

<portType name="calcPortType">
 <operation name="add">
  <documentation>Service definition of function ns__add</documentation>
  <input message="tns:addRequest"/>
  <output message="tns:addResponse"/>
 </operation>
 <operation name="sub">
  <documentation>Service definition of function ns__sub</documentation>
  <input message="tns:subRequest"/>
  <output message="tns:subResponse"/>
 </operation>
 <operation name="mul">
  <documentation>Service definition of function ns__mul</documentation>
  <input message="tns:mulRequest"/>
  <output message="tns:mulResponse"/>
 </operation>
 <operation name="div">
  <documentation>Service definition of function ns__div</documentation>
  <input message="tns:divRequest"/>
  <output message="tns:divResponse"/>
 </operation>
 <operation name="pow">
  <documentation>Service definition of function ns__pow</documentation>
  <input message="tns:powRequest"/>
  <output message="tns:powResponse"/>
 </operation>
</portType>

<binding name="calc" type="tns:calcPortType">
 <SOAP:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
 <operation name="add">
  <SOAP:operation style="rpc" soapAction=""/>
  <input>
     <SOAP:body use="encoded" namespace="urn:calc" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
  </input>
  <output>
     <SOAP:body use="encoded" namespace="urn:calc" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
  </output>
 </operation>
 <operation name="sub">
  <SOAP:operation style="rpc" soapAction=""/>
  <input>
     <SOAP:body use="encoded" namespace="urn:calc" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
  </input>
  <output>
     <SOAP:body use="encoded" namespace="urn:calc" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
  </output>
 </operation>
 <operation name="mul">
  <SOAP:operation style="rpc" soapAction=""/>
  <input>
     <SOAP:body use="encoded" namespace="urn:calc" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
  </input>
  <output>
     <SOAP:body use="encoded" namespace="urn:calc" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
  </output>
 </operation>
 <operation name="div">
  <SOAP:operation style="rpc" soapAction=""/>
  <input>
     <SOAP:body use="encoded" namespace="urn:calc" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
  </input>
  <output>
     <SOAP:body use="encoded" namespace="urn:calc" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
  </output>
 </operation>
 <operation name="pow">
  <SOAP:operation style="rpc" soapAction=""/>
  <input>
     <SOAP:body use="encoded" namespace="urn:calc" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
  </input>
  <output>
     <SOAP:body use="encoded" namespace="urn:calc" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
  </output>
 </operation>
</binding>

<service name="calc">
 <documentation>gSOAP 2.7.9k generated service definition</documentation>
 <port name="calc" binding="tns:calc">
  <SOAP:address location="http://websrv.cs.fsu.edu/~engelen/calcserver.cgi"/>
 </port>
</service>

</definitions>

开始贴代码(calc.h): 我生成的 *.h文件和下面的不一样,看上去可能是gsoap的版本升级造成的。或者是生产了c++的代码

wsdl2h常用选项

-o 文件名,指定输出头文件

-n 名空间前缀 代替默认的ns

-c 产生纯C代码,否则是C++代码

-s 不要使用STL代码

-t 文件名,指定type map文件,默认为typemap.dat

-e 禁止为enum成员加上名空间前缀

 

 

//gsoap ns service name:   calc
//gsoap ns  service port:  http://localhost/calc.wsdl
//gsoap ns service location:   http://localhost
//gsoap ns service executable: calc.cgi
//gsoap ns service encoding:   encoded
//gsoap ns service type:   calcPortType
 
 
//gsoap ns schema namespace: urn:add
 
//gsoap ns service method-documentation: add Sums two values
 
int ns__add(double a, double b, double *result);
 
//gsoap ns service method-documentation: sub Subtracts two values
 
int ns__sub(double a, double b, double *result);
 
//gsoap ns service method-documentation: mul Multiplies two values
 
int ns__mul(double a, double b, double *result);
 
//gsoap ns service method-documentation: div Divides two values
 
int ns__div(double a, double b, double *result);
 
//gsoap ns service method-documentation: pow Raises a to b
int ns__pow(double a, double b, double *result);


 

生成源文件:
 soapcpp2 头文件
常用选项
-C 仅生成客户端代码
-S 仅生成服务器端代码
-L 不要产生soapClientLib.c和soapServerLib.c文件
-c 产生纯C代码,否则是C++代码(与头文件有关)
-I 指定import路径(见上文)
-x 不要产生XML示例文件
-i 生成C++包装,客户端为xxxxProxy.h(.cpp),服务器端为xxxxService.h(.cpp)。
在cmd命令行下进入工程目录,执行: 
soapcpp2  -L -w -x -I D:\study\gSOAP\code\gsoap\import calc.h
即生成一堆文件,包括客户端和服务端框架代码。

第三步:编写服务端程序

#include "soapH.h"
#include "calc.nsmap"
#include "stdsoap2.h"
#include <stdio.h>
#include <stdlib.h>
 
int main(int argc, char **argv)
{ 
    SOAP_SOCKET m, s; /* master and slave sockets */
    struct soap soap;
    soap_init(&soap);
 
    if (argc < 2)
        soap_serve(&soap);   /* serve as CGI application */
    else{ 
        m = soap_bind(&soap, NULL, atoi(argv[1]), 100);
 
        if (!soap_valid_socket(m)){ 
            soap_print_fault(&soap, stderr);
            exit(-1);
        }
 
        fprintf(stderr, "Socket connection successful: master socket = %d\n", m);
 
        for ( ; ; ){
            s = soap_accept(&soap);
            fprintf(stderr, "Socket connection successful: slave socket = %d\n", s);
 
            if (!soap_valid_socket(s)){ 
                soap_print_fault(&soap, stderr);
                exit(-1);
            }
 
            soap_serve(&soap);
            soap_end(&soap);
        }
    }
 
    return 0;
}
 
int ns__add(struct soap *soap, double a, double b, double *result)
{ 
    *result = a + b;
    return SOAP_OK;
}
 
int ns__sub(struct soap *soap, double a, double b, double *result)
{ 
    *result = a - b;
    return SOAP_OK;
}
 
int ns__mul(struct soap *soap, double a, double b, double *result)
{
    *result = a * b;
    return SOAP_OK;
}
 
int ns__div(struct soap *soap, double a, double b, double *result)
{ 
    if (b)
        *result = a / b;
    else{ 
        char *s = (char*)soap_malloc(soap, 1024);
        sprintf(s, "<error xmlns=\"http://tempuri.org/\">Can't divide %f by %f</error>", a, b);
        return soap_sender_fault(soap, "Division by zero", s);
    }
 
    return SOAP_OK;
}
 
int ns__pow(struct soap *soap, 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(soap, 1024);
        sprintf(s, "Can't take the power of %f to %f", a, b);
        sprintf(s, "<error xmlns=\"http://tempuri.org/\">Can't take power of %f to %f</error>", a, b);
        return soap_sender_fault(soap, "Power function domain error", s);
    }
 
    return SOAP_OK;
}

第四步:编写客户端程序

#include "soapH.h"
#include "calc.nsmap"
#include <stdio.h>
#include <stdlib.h>
#include "stdsoap2.h"
 
const char server[] = "http://localhost:4546";//"http://websrv.cs.fsu.edu/~engelen/calcserver.cgi";
/* = "http://localhost:8080"; to test against samples/webserver */
 
int main(int argc, char **argv)
{ 
    struct soap soap;
    double a, b, result;
 
    if (argc < 4){
        fprintf(stderr, "Usage: [add|sub|mul|div|pow] num num\n");
        exit(0);
    }
 
    soap_init1(&soap, SOAP_XML_INDENT);
    //soap_init(&soap);
    //printf("add(%f,%f) \n",argv[2],argv[3]);
 
    a = strtod(argv[2], NULL);
    b = strtod(argv[3], NULL);
 
    switch (*argv[1])
    { 
    case 'a':
        printf("add(%f,%f) \n",a,b);
        soap_call_ns__add(&soap, server, NULL, a, b, &result);
        break;
    case 's':
        soap_call_ns__sub(&soap, server, "", a, b, &result);
        break;
    case 'm':
        soap_call_ns__mul(&soap, server, "", a, b, &result);
        break;
    case 'd':
        soap_call_ns__div(&soap, server, "", a, b, &result);
        break;
    case 'p':
        soap_call_ns__pow(&soap, server, "", a, b, &result);
        break;
    default:
        fprintf(stderr, "Unknown command\n");
        exit(0);
    }
 
    if (soap.error){
        printf("abcd\n");
        soap_print_fault(&soap, stderr);
        exit(1);
    } else 
        printf("result = %f\n", result);
 
    soap_destroy(&soap);
    soap_end(&soap);
    soap_done(&soap);
 
    return 0;
}

--------------------- 
作者:河东酷神 
来源:CSDN 
原文:https://blog.csdn.net/qianqiuwanzi/article/details/24120455 
版权声明:本文为博主原创文章,转载请附上博文链接!

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值