`
panxq0809
  • 浏览: 296836 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论
阅读更多
gsoap心得
2009-12-08 13:10
gSOAP是一个绑定SOAP/XML到C/C++语言的工具,使用它可以 简单快速地开发出SOAP/XML的服务器端和客户端。由于gSOAP具有相当不错的兼容性,通过gSOAP,我们就可以调用由Java, .Net, Delhpi, PHP等语言开发的SOAP服务,或者向它们提供SOAP服务。
gSOAP是一个绑定SOAP/XML到C/C++语言的工具,使用它可以简单快速地开发出SOAP/XML的服务器端和客户端。由于 gSOAP具 有相当不错的兼容性,通过gSOAP,我们就可以调用由Java, .Net, Delhpi, PHP等语言开发的SOAP服务,或者向它们提供SOAP服务。

gSOAP的主页是:

http://sourceforge.net/projects/gsoap2

下载解压后,可以在gsoap\bin\win32里 找到wsdl2h.exe和soapcpp2.exe(另外还有linux和mac版本)。

wsdl2h.exe的作用是根据WSDL生成C/C++风格的头 文件
soapcpp2.exe的作用是根据头文件自动生成调用远程 SOAP服务的客户端代码(称为存根:Stub)和提供SOAP服务的框架代码(称为框架:Skeleton),另外它也能从头文件生成WSDL文件。
gsoap\stdsoap2.cpp则是gSOAP的核心代码,要使用 gSOAP只要在项目里包含这个文件以及由soapcpp2.exe生成的代码即可。另外还有个stdsoap2.c,内容与stdsoap2.cpp一 模一样,用于纯C项目。

gSOAP两大工具的用法
从WSDL中产生头文件
用法:
wsdl2h -o 头文件名 WSDL文件名或URL
wsdl2h常用选项
-o 文件名,指定输出头文件
-n 名空间前缀 代替默认的ns
-c 产生纯C代码,否则是C++代码
-s 不要使用STL代码
-t 文件名,指定type map文件,默认为typemap.dat
-e 禁止为enum成员加上名空间前缀
type map文件用于指定SOAP/XML中的类型与C/C++之间的转换规则,比如在wsmap.dat里写

xsd__string = | std::wstring | wchar_t*
那么SOAP/XML中的string将转换成std::wstring或wchar_t*,这样能更好地支持中文。

例:

wsdl2h -o ayandy.h \ -n ay -t wsmap.dat \ http://www.ayandy.com/Service.asmx?WSDL
从http://www.ayandy.com/Service.asmx?WSDL 生成ayandy.h文件,名空间为ay,使用wsmap.dat指定的转换规则。

wsdl2h生成的头文件里的变量、类型等名称的前面都会加上名空间前缀,以两个下划线分隔。如上面的命令生成的头文件,有这样的定 义:

class ay1__ArrayOfString;
enum ay1__theDayFlagEnum
{
ay1__theDayFlagEnum__Today,
ay1__theDayFlagEnum__Tomorrow,
ay1__theDayFlagEnum__theDayafterTomorrow,
};

前面的ayandy1__的是名空间前缀,用以防止名称冲突。 wsdl2h的-n选项可以改变这个名空间前缀(默认为ns)。对于枚举ay1__theDayFlagEnum内 的成员,如果嫌它太长的话,可以用-e命令选项禁止加入名空间前缀。

从头文件生成存根(stub)和框架(Skeleton)源文件
编写SOAP程序除了头文件是不够的,还要有连接、通信、XML解析、序列/反序列化等工作。gSOAP提供的socapcpp2.exe就 是用于从头文件中生成这些代码的,我们只要关心真正的业务逻辑就行了。

用法
soapcpp2 头文件
例:
soapcpp2 ayandy.h
将生成下面这些文件

soapStub.h    // soap的存根文件,定义了ayandy.h里对应的远程调用模型
soapC.c soapH.h // soap的序列和反序列代码,它已经包含了soapStub.h,服务器端与客户端都要包含它
soapClient.c soapClientLib.c // 客户端代码,soapClientLib.c文件则只是简单地包含soapClient.c和soapC.c
soapServer.c soapServerLib.c // 服务器端代码,soapServerLib.c文件则只是简单地包含soapServer.c和soapC.c
ServiceSoap.nsmap ServiceSoap12.nsmap // 名空间定义,服务器端与客户端都要包含它
soapServiceSoapProxy.h soapServiceSoap12Proxy.h // 客户端的C++简单包装(如果头文件是纯C代码,这两个文件就不会生成)
综上所述

如果编写服务器端,项目里应该加入soapServerLib.c,代码里包含头文件soapH.h
如果编写客户端,项目里应该加入soapClientLib.c,代码里包含头文件SoapH.h(或xxxxProxy.h)
当然,还要加入gsoap库里的stdsoap2.cpp文件(如果是写C代码,则加入stdsoap2.c)
如果看到soapcpp2提示:”Critical error: #import: Cannot open file "stlvector.h" for reading.“, 那是因为我们的头文件使用了STL(wsdl2h 没用-s选项),这时要使用-I选项指定gSOAP的 import文件路径,这个路径是"$gsoap\gsoap\import":

soapcpp2 ayandy.h -I D:\gsoap-2.7\gsoap\import
soapcpp2常用选项
-C 仅生成客户端代码
-S 仅生成服务器端代码
-L 不要产生soapClientLib.c和soapServerLib.c文件
-c 产生纯C代码,否则是C++代码(与头文件有关)
-I 指定import路径(见上文)
-x 不要产生XML示例文件
-i 生成C++包装,客户端为xxxxProxy.h(.cpp),服务器端为xxxxService.h(.cpp)。
编写SOAP客户端
下面将演示使用gSOAP到网上取得天气预报,互联网上有不少网站提供SOAP服务,比如Google提供的搜索API(现在已不再提 供新的License Key了),不少博客提供的API等。这里介绍一个提供天气预报服务的SOAP服务,地址是http://www.ayandy.com

它提供了三个函数:
getSupportCity 查询本天气WebService支持的城市信息。
getSupportProvince 查询本天气 WebService支持的省份信息。
getWeatherbyCityName 根据城市名称获得天 气情况。
它的WSDL地址是http://www.ayandy.com/Service.asmx?WSDL

现在,我们编写一个客户端去调用getWeatherbyCityName来 取得天气情况

1. 从WSDL得到头文件
wsdl2h -o ayandy.h http://www.ayandy.com/Service.asmx?WSDL

2. 从头文件得到存根(Stub)源文件
soapcpp2 -i -C -x ayandy.h -ID:\gsoap-2.7\gsoap\import

命令选项注释:
-i 直接使用C++包装类
-x 不要生成一堆看了就恶心的xml
-C 只生成客户端相关代码
-I 指定import路径3. 建立新项目
把gsoap库里的stdsoap2.cpp文件,以及上一步生成的soapServiceSoapProxy.cpp和soapC.cpp都加入到项 目。

设置加入的这三个文件为不使用预编译头。

4. 编写代码
由于参数及回传的数据都是中文,所有让gSOAP使用UTF8方式传送以防止乱码。

#include <iostream>
#include <string>
#include "soapServiceSoapProxy.h"
#include& nbsp;"ServiceSoap.nsmap" //表忘了名空间定义

using namespace std;

// 宽 字符转UTF8
string EncodeUtf8(wstring in)
{
     string s(in.length()*3+1,' ');
    size_t len = ::WideCharToMultiByte(CP_UTF8, 0,
             in.c_str(), in.length(),
             &s[0], s.length(),
             NULL, NULL);
     s.resize(len);
    return s;
}

// UTF8 转宽字符
wstring DecodeUtf8(string in)
{
     wstring s(in.length(), _T(' '));
    size_t len = ::MultiByteToWideChar(CP_UTF8, 0,
             in.c_str(), in.length(),
             &s[0], s.length());
     s.resize(len);
    return s;
}

int main(int argc, char* argv[])
{
     ServiceSoapProxy gs(SOAP_C_UTFSTRING);

     _ns1__getWeatherbyCityName cityname;
     _ns1__getWeatherbyCityNameResponse resp;

     string strCityName = EncodeUtf8(L"苏州");
     cityname.theCityName = &strCityName;
     cityname.theDayFlag = ns1__theDayFlagEnum__Tomorrow;

    if(gs.getWeatherbyCityName(&cityname, &resp) == SOAP_OK)
     {
         ns1__ArrayOfString *aos = resp.getWeatherbyCityNameResult;
         wcout.imbue( std::locale("chs") ); //指定输出为中文
        for(vector<string>::iterator
                 itr=aos->string.begin(), itr_end = aos->string.end();
                 itr!=itr_end; ++itr)
             wcout << DecodeUtf8(*itr) << endl;

     }

    return 0;
}

上面的代码花了一半在UTF8编码转换上,如果参数里没有中文的话,代码会简化很多:

ServiceSoapProxy gs;
_ns1__getWeatherbyCityName cityname;
_ns1__getWeatherbyCityNameResponse resp;
string strCityName("苏州");
cityname.theCityName = &strCityName;
cityname.theDayFlag = ns1__theDayFlagEnum__Tomorrow;

if(gs.getWeatherbyCityName(&cityname, &resp) == SOAP_OK)
{
     ns1__ArrayOfString *aos = resp.getWeatherbyCityNameResult;
    for(vector<string>::iterator
             itr=aos->string.begin(), itr_end = aos->string.end();
             itr!=itr_end; ++itr)
         cout << *itr << endl;
}

但是这个代码应用到中文字符串时,会发现返回的是一堆乱码,gSOAP有两种方式支持它:

使用宽字符集,如用前文演示的type map文件来转换字符串为std::wstring。
使用UTF8传送字符串,这个例子就是使用的这个方式:首先,定义ServiceSoapProxy gs的传送模式为SOAP_C_UTFSTRING;然后输入时把字符串转换成UTF8,得到输出时把UTF8转换回来。
使用UTF8时还要注意一点,如果使用纯C调用,那么应该这样设置UTF8调用:

soap sp;
soap_init(&sp);
soap_set_mode(&sp, SOAP_C_UTFSTRING);
sp.mode |= SOAP_C_UTFSTRING; //关键

也许是gSOAP的bug吧,soap_set_mode只 设置了sp.imode和sp.omode两个成员,却没有设置sp.mode。跟踪代码可以发现从服务器传回数据后,gSOAP是根据sp.mode来 决定是否使用UTF8转换的。

编写SOAP服务器
现在,我们自己动手写一个天气预报服务,当然,是乱报的啦,呵呵。

1.这次,我们尝试使用宽字符集的方式来支持中文
写一个wsmap.dat文件,里面写上:xsd__string = | std::wstring | std::wstring*

2.从WSDL生成头文件
wsdl2h.exe -o ayandy.h -t wsmap.dat -e http://www.ayandy.com/Service.asmx?WSDL

命令选项注释:
-o ayandy.h 生成ayandy.h头文件
-t wsmap.dat 根据wsmap.dat规则转换数据类型
-e 枚举成员不要有长长的名空间前缀
3.从头文件生成服务器框架代码
soapcpp2 ayandy.h -i -x -S -I D:\Code\libs\gsoap-2.7\gsoap\import

命令选项注释:
-S 仅生成服务器框架代码
4.新建项目
把gsoap库里的stdsoap2.cpp文件,以及上一步生成的soapServiceSoapService.cpp和soapC.cpp都加入到 项目。

设置加入的这三个文件为不使用预编译头。

5.编写代码
打开soapcpp2生成的soapServiceSoapService.h文件,在ServiceSoapService类定义里 会看到这样几行字:

///
/// Service operations (you should define these):
///

它后面的几个方法是要我们自己实现它的,先看代码吧:

#include "soapServiceSoapService.h"
#include "ServiceSoap.nsmap"

/// Web service operation 'getWeatherbyCityName' (returns error code or SOAP_OK)
int ServiceSoapService::getWeatherbyCityName(
         _ns1__getWeatherbyCityName *ns1__getWeatherbyCityName,
         _ns1__getWeatherbyCityNameResponse *ns1__getWeatherbyCityNameResponse)
{
    if(*(ns1__getWeatherbyCityName->theCityName) != L"苏州") return SOAP_USER_ERROR;

     ns1__ArrayOfString * aos = soap_new_ns1__ArrayOfString(this, -1);

     aos->string.push_back( std::wstring() ); //第0个空着
    if(ns1__getWeatherbyCityName->theDayFlag != Tomorrow)
     {
         aos->string.push_back( L"我只知道明天天气,其它的不要问我!" );
     }
    else
     {
         aos->string.push_back( L"有日食,不过下大雨,哈哈,气死你!" );
         aos->string.push_back( L"下雨当然有风啦,多大我也不知道" );
     }
     ns1__getWeatherbyCityNameResponse->getWeatherbyCityNameResult = aos;
    return SOAP_OK;
}

/// Web service operation 'getSupportProvince' (returns error code or SOAP_OK)
int ServiceSoapService::getSupportProvince(
         _ns1__getSupportProvince *ns1__getSupportProvince,
         _ns1__getSupportProvinceResponse *ns1__getSupportProvinceResponse)
{
    return SOAP_OK;
}

/// Web service operation 'getSupportCity' (returns error code or SOAP_OK)
int ServiceSoapService::getSupportCity(
         _ns1__getSupportCity *ns1__getSupportCity,
         _ns1__getSupportCityResponse *ns1__getSupportCityResponse)
{
    return SOAP_OK;
}


int main(int argc, char* argv[])
{
     ServiceSoapService sev;
    return sev.run(8888);//本机8888端口
}

编译,运行,现在我们的本机8888端口开始提供天气预报的SOAP服务了。

修改之前的客户端,在main()里第一行

ServiceSoapProxy gs(SOAP_C_UTFSTRING);

后面加上:

gs.soap_endpoint="http://localhost:8888";

运行这客户端后可以就看到我们提供的优质服务了:)

本例中getWeatherbyCityName方 法里的ns1__getWeatherbyCityNameResponse参 数用于返回数据,它的getWeatherbyCityNameResult成 员是由我们来申请内存的,这个内存应该用“soap_new_ 类名”来取得,这些申请函数可以从soapH.h里找到,如本例的soap_new_ns1__ArrayOfString。

第一个参数是soap类型,它是ServiceSoapService的父类型,也是gSOAP中最重要的类型。
第二个指定申请的个数,指定为-1表示只生成一个,否则生成一个指定数目的数组。

忘了从哪里转的了
分享到:
评论
1 楼 gaowei52306 2011-03-26  

相关推荐

    gsoap使用方法及心得

    gsoap使用方法及心得

    gsoap.rar_gSoap-2.8_gsoap_gsoap vc6_gsoap使用详解

    gSOAP(Generic SOAP)是一个开源C++库,用于构建基于Web服务的应用程序。它支持SOAP(Simple Object Access Protocol)协议,使开发者能够实现客户端和服务端的互操作性,跨越不同的操作系统和编程语言。gSOAP 2.8...

    gsoap_2.8.45.zip_gsoap_gsoap 2.8_gsoap_2.8.45

    gsoap,直接下载,调用函数即可,实现通讯

    gsoap 2.8.71

    gSOAP 编译工具提供了一个SOAP关于C/C++ 语言的实现,从而让C/C++语言开发Web Services服务端或客户端程序的工作变得轻松了很多。甚至,即使你对Web Services不甚了解都没有关系,有了gSOAP这样的工具,你也能开发...

    gsoap 2.8 完整工具包

    gSOAP(Generic SOAP)是一个开源项目,用于生成C和C++代码,以便在不同系统间进行Web服务通信。gSOAP 2.8是这个项目的最新版本,它包含了全面的工具和库,支持Windows、Linux以及macOS等操作系统,确保了跨平台的...

    gsoap http webapi

    1. 配置gSOAP:首先,需要下载并安装gSOAP,然后使用gSOAP的wsdl2h工具生成服务头文件,该文件包含了Web API接口的定义。 2. 编码请求:使用gSOAP提供的库函数,如soap_init()初始化SOAP环境,然后设置HTTP GET请求...

    gsoap2.8实现onvif协议

    1. **gSOAP简介**: gSOAP是一个开源的C/C++软件开发工具包,它提供了一套自动代码生成器,用于处理SOAP消息。gSOAP能够解析WSDL(Web服务描述语言)文件,自动生成客户端和服务器端的代理代码,简化了Web服务的开发...

    gsoap最新版本gsoap_2.8.19

    gsoap最新版本最新版本,C/C++调用Web Service需要用到soap库,一般使用的有gsoap和axis cpp两种实现,这里使用gsoap来调用。gsoap是sourceforge上的一个开源项目,目前版本是2.7.6c,使用简单,可以在 linxu、...

    gsoap

    **gSOAP:深入理解与应用** gSOAP是一个开源的C/C++软件开发工具包,用于构建基于Web服务的客户端和服务器应用程序。它提供了一种高效、灵活的方式来处理SOAP(Simple Object Access Protocol)消息,这是一种XML...

    c++ gsoap webservice文件传送demo

    在本文中,我们将深入探讨如何在Windows 7环境下,利用Visual C++(VC)和gSOAP库实现Web服务文件传输的示例。gSOAP是一个开源的C和C++ Web服务工具包,它允许开发者轻松地创建和使用SOAP(简单对象访问协议)服务,...

    gSoap.rar软件

    gSoap是一款开源的C/C++库,用于构建网络服务客户端和服务端应用程序。它支持SOAP(简单对象访问协议)和Web服务标准,使开发者能够轻松地实现跨平台的HTTP通信。在这款软件中,"gSoap.rar"可能包含了gSoap库的所有...

    gsoap_2.7 linux下安装_命令使用

    **gSOAP 2.7 在 Linux (RHEL) 下的安装与命令使用详解** gSOAP 是一个开源的软件开发工具包,它允许程序员在 C/C++ 中创建基于 Web 服务的应用程序。gSOAP 支持多种协议,如 SOAP、HTTP 和 HTTPS,并提供了自动的...

    gSOAP2.8源码包

    gSOAP2.8源码包是一个强大的开源工具,专为跨平台Web Service开发设计,支持Windows、Linux、Mac OS以及UNIX等操作系统。该工具的核心特性是利用C和C++编程语言,使得开发者能够轻松构建服务端和客户端应用程序,...

    gsoap_2.8.87.zip

    gSOAP(Generic SOAP)是一个开源项目,主要用于C和C++编程语言,提供了一整套工具和库,使得开发者能够方便地实现SOAP(Simple Object Access Protocol)协议,进行Web服务的开发和客户端应用的构建。标题中的...

    gSOAP的中文文档

    ### gSOAP:构建高效Web服务的关键工具 #### 引言 在现代软件开发领域,特别是Web服务的构建与集成过程中,gSOAP(Global Systems for Mobile Communications Association SOAP)扮演着举足轻重的角色。作为一款...

    gsoap开发包 C/C++开发webservice用到的gsoap开发包

    gSOAP(Generic SOAP)是一个开源库,用于C和C++编程语言,专为构建Web服务客户端和服务端应用程序而设计。这个开发包是针对C/C++开发者的重要工具,它提供了处理XML数据和SOAP协议的能力,使得在不同的系统和平台...

    gsoap_2.8.8.zip

    《gSOAP 2.8.8在VC环境下的Web服务开发详解》 gSOAP是一个开源的C/C++软件工具包,专为构建基于SOAP(Simple Object Access Protocol)的Web服务和客户端应用程序而设计。gSOAP 2.8.8版本是这个强大库的一个更新,...

    GSOAP2.8.49

    **gSOAP 2.8.49:C++ Webservice接口开发神器** gSOAP是一个开源的C和C++编程库,用于构建Web服务客户端和服务器应用程序。它支持SOAP(Simple Object Access Protocol)和WSDL(Web Services Description Language...

    gsoap-2.8工具

    **gSOAP工具详解** gSOAP(GenericSOAP)是一款强大的开源工具,主要面向C和C++开发者,用于构建网络服务和客户端应用。它支持基于Web Services Description Language (WSDL) 的SOAP(Simple Object Access ...

    根据wsdl使用gsoap生成的服务器和客户端

    本文将深入探讨如何利用gSOAP工具根据WSDL文件生成C或C++语言的服务器和客户端代码,以实现Web服务的开发。 1. **WSDL简介**: WSDL文件描述了Web服务的接口,包括服务的位置、提供的操作以及如何调用这些操作。它...

Global site tag (gtag.js) - Google Analytics