用gSOAP调用Web Services
- 格式:doc
- 大小:51.50 KB
- 文档页数:18
使用gSOAP进行Webservice开发总结1.概述Web service是创建可互操作的分布式应用程序的新平台。
Web service 的主要目标是跨平台的可互操作性。
为了达到这一目标,Web service 是完全基于XML、XSD等独立于平台、独立于软件供应商的标准的。
Web service在应用程序跨平台和跨网络进行通信的时候是非常有用的。
Web service 适用于应用程序集成、B2B集成、代码和数据重用,以及通过Web进行客户端和服务器的通信的场合。
南京内容与资源管理中心需要为第三方提供DNA识别的接口,由于第三方可能位于不同的局域网中,运行于不同的平台,以及第三方形式多样化,为此提供一种通用的接口至关重要。
鉴于Web service在跨平台,跨网络方面的出色表现,南京内容与资源管理中心需要采用Web service为第三方提供DNA识别接口。
南京内容与资源管理中心采用C/C++ 实现,如何快速的实现Web service接口呢?开源项目gsoap为此提供了很好的解决方案。
2.gSOAP介绍gSOAP是一个绑定SOAP/XML到C/C++语言的工具,使用它可以简单快速地开发出SOAP/XML的服务器端和客户端。
由于gSOAP 具有相当不错的兼容性,通过gSOAP,我们就可以调用由Java, .Net, Delhpi, PHP等语言开发的SOAP服务,或者向它们提供SOAP服务。
gSOAP的编译器能够自动的将用户定义的本地化的C或C++数据类型转变为符合XML语法的数据结构,反之亦然。
这样,只用一组简单的API就将用户从SOAP细节实现工作中解脱了出来,可以专注与应用程序逻辑的实现工作了。
gSOAP编译器可以集成C/C++和Fortran代码(通过一个Fortran到C的接口),嵌入式系统,其他SOAP程序提供的实时软件的资源和信息;可以跨越多个操作系统,语言环境以及在防火墙后的不同组织。
2011.11在C/C++环境下基于gSoap 实现Web Services 调用罗学刚1gSoap 介绍在C/C++环境下实现一个通用性较强的Web Services 客户端一直是比较麻烦的事,gSoap 的出现让这个工作简单了很多。
目前多数支持C/C++的Web 服务工具包都是提供一组API 函数类库来处理特定的SOAP 数据结构,这样就使得用户必须改变程序结构来适应相关的类库。
然而,gSoap 是利用编译器技术提供了一组透明化的SOAP API ,并将和开发工作无关的SOAP 实现细节隐藏起来。
gSoap 的编译器能够自动的将用户定义的本地化的C/C++数据类型转变为符合XML 语法的数据结构,反之亦然。
这样,只用一组简单的API 就将用户从SOAP 细节实现工作中解脱了出来,能够专注和应用程序逻辑的实现工作中去。
gSoap 编译器能够集成C/C++和Fortran 代码(通过一个Fortran 到C 的接口),嵌入式系统,其他SOAP 程序提供的实时软件的资源和信息;能够跨越多个操作系统,多种语言环境连同在防火墙后的不同组织。
gSoap 使编写Web 服务的工作大大简化。
通过gSoap 编译器来生成SOAP 代码来序列化或反序列化C/C++的数据结构。
gSoap 包含一个WSDL 生成器,用它来为您的Web服务生成Web 服务的解释。
gSoap 的解释器及导入器能够使用户无需分析Wed 服务的细节就能够实现一个客户端或服务端程序。
2开发准备下载gSoap 工具的代码地址,当前最新版本是2.8.0版本:/projects/gsoap2/。
解压下载文件到本地目录,进入bin 目录。
可以在gsoap\bin\win32里找到wsdl2h.exe 和soapcpp2.exe (另外还有linux 和mac 版本)。
wsdl2h.exe 的作用是根据WSDL 生成C/C++风格的头文件。
soapcpp2.exe 的作用是根据头文件自动生成调用远程SOAP 服务的客户端代码(称为存根:Stub )和提供SOAP 服务的框架代码(称为框架:Skeleton ),另外它也能从头文件生成WSDL 文件。
基于gSOAP的WebService开发指导说明书1简介1.1目的本文通过给出gSOAP库的基本使用样例,帮助开发人员进行WebService相关的开发1.2范围本文只包含gSOAP库C++版本的基本使用样例,不包含其他高级使用或C版本的使用方式1.3名词解释1.4参考资料2准备工作2.1gSOAP库很显然,要想基于gSOAP库开发WebService应用,你需要首先获取gSOAP库。
gSOAP库是一个开源库,你可以在以下网址进行下载:/project/showfiles.php?group_id=52781如果链接失效,也可以去一个介绍gSOAP的网站上查看最新下载地址:/~engelen/soap.html本文所用的版本为(soapcpp2):下载下来以后解压缩,你会得到这么一个目录:其中gsoap目录有以下结构:注意这两个文件:stdsoap2.h和stdsoap2.cpp,我们编写gSOAP程序的时候是需要它们的。
还要注意的是bin\win32目录下的两个可执行文件:soapcpp2.exe和wsdl2h.exe,目前我们只需要soapcpp2.exe。
也就是说,要使用gSOAP,我们需三个文件:解压目录\gsoap-2.8\gsoap\ stdsoap2.h解压目录\gsoap-2.8\gsoap\ stdsoap2.cpp解压目录\gsoap-2.8\gsoap\bin\win32\ soapcpp2.exe使用gSOAP不需要在程序中添加额外的库,而是要通过工具生成并包含额外的文件。
接下来,我们通过一个实例去了解如何使用gSOAP提供的这三个文件。
3创建一个WebService服务端工程gSOAP使用了代码生成器帮助我们生成一些辅助性的框架与类,所以我们想要使用gSOAP,则需要做一些额外的工作。
下面我们就从零开始构建一个使用gSOAP的服务端工程。
3.1新建一个工程这一步没什么难度,使用VS直接新建一个工程即可。
C#通过Get、Post、Soap调⽤WebService的⽅法实现代码来源于⽹络,我只是作了⼀些修改!using System;using System.Web;using System.Xml;using System.Collections;using ;using System.Text;using System.IO;using System.Xml.Serialization;/// <summary>/// 利⽤WebRequest/WebResponse进⾏WebService调⽤的类/// </summary>public class WebServiceHelper{//<webServices>// <protocols>// <add name="HttpGet"/>// <add name="HttpPost"/>// </protocols>//</webServices>private static Hashtable _xmlNamespaces = new Hashtable();//缓存xmlNamespace,避免重复调⽤GetNamespace/// <summary>/// 需要WebService⽀持Post调⽤/// </summary>public static XmlDocument QueryPostWebService(String URL, String MethodName, Hashtable Pars){HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(URL + "/" + MethodName);request.Method = "POST";request.ContentType = "application/x-www-form-urlencoded";SetWebRequest(request);byte[] data = EncodePars(Pars);WriteRequestData(request, data);return ReadXmlResponse(request.GetResponse());}/// <summary>/// 需要WebService⽀持Get调⽤/// </summary>public static XmlDocument QueryGetWebService(String URL, String MethodName, Hashtable Pars){HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(URL + "/" + MethodName + "?" + ParsToString(Pars));request.Method = "GET";request.ContentType = "application/x-www-form-urlencoded";SetWebRequest(request);return ReadXmlResponse(request.GetResponse());}/// <summary>/// 通⽤WebService调⽤(Soap),参数Pars为String类型的参数名、参数值/// </summary>public static XmlDocument QuerySoapWebService(String URL, String MethodName, Hashtable Pars){if (_xmlNamespaces.ContainsKey(URL)){return QuerySoapWebService(URL, MethodName, Pars, _xmlNamespaces[URL].ToString());}else{return QuerySoapWebService(URL, MethodName, Pars, GetNamespace(URL));}}/// <summary>/// 通⽤WebService调⽤(Soap)/// </summary>/// <param name="URL"></param>/// <param name="MethodName"></param>/// <param name="Pars"></param>/// <param name="XmlNs"></param>/// <returns></returns>private static XmlDocument QuerySoapWebService(String URL, String MethodName, Hashtable Pars, string XmlNs){_xmlNamespaces[URL] = XmlNs;//加⼊缓存,提⾼效率HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(URL);request.Method = "POST";request.ContentType = "text/xml; charset=utf-8";request.Headers.Add("SOAPAction", "\"" + XmlNs + (XmlNs.EndsWith("/") ? "" : "/") + MethodName + "\"");SetWebRequest(request);byte[] data = EncodeParsToSoap(Pars, XmlNs, MethodName);WriteRequestData(request, data);XmlDocument doc = new XmlDocument(), doc2 = new XmlDocument();doc = ReadXmlResponse(request.GetResponse());XmlNamespaceManager mgr = new XmlNamespaceManager(Table);mgr.AddNamespace("soap", "/soap/envelope/");String RetXml = doc.SelectSingleNode("//soap:Body/*/*", mgr).InnerXml;doc2.LoadXml("<root>" + RetXml + "</root>");AddDelaration(doc2);return doc2;}/// <summary>/// 通过WebService的WSDL获取XML名称空间/// </summary>/// <param name="URL"></param>/// <returns></returns>private static string GetNamespace(String URL){HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL + "?WSDL");SetWebRequest(request);WebResponse response = request.GetResponse();StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.UTF8);XmlDocument doc = new XmlDocument();doc.LoadXml(sr.ReadToEnd());sr.Close();return doc.SelectSingleNode("//@targetNamespace").Value;/// 动态⽣成SOP请求报⽂内容/// </summary>/// <param name="Pars"></param>/// <param name="XmlNs"></param>/// <param name="MethodName"></param>/// <returns></returns>private static byte[] EncodeParsToSoap(Hashtable Pars, String XmlNs, String MethodName){XmlDocument doc = new XmlDocument();doc.LoadXml("<soap:Envelope xmlns:xsi=\"/2001/XMLSchema-instance\" xmlns:xsd=\"/2001/XMLSchema\" xmlns:soap=\"/soap/envelope/\"></soap:Envelope>"); AddDelaration(doc);XmlElement soapBody = doc.CreateElement("soap", "Body", "/soap/envelope/");XmlElement soapMethod = doc.CreateElement(MethodName);soapMethod.SetAttribute("xmlns", XmlNs);foreach (string k in Pars.Keys){XmlElement soapPar = doc.CreateElement(k);soapPar.InnerXml = ObjectToSoapXml(Pars[k]);soapMethod.AppendChild(soapPar);}soapBody.AppendChild(soapMethod);doc.DocumentElement.AppendChild(soapBody);return Encoding.UTF8.GetBytes(doc.OuterXml);}/// <summary>/// 将对象转换成XML节点格式/// </summary>/// <param name="o"></param>/// <returns></returns>private static string ObjectToSoapXml(object o){XmlSerializer mySerializer = new XmlSerializer(o.GetType());MemoryStream ms = new MemoryStream();mySerializer.Serialize(ms, o);XmlDocument doc = new XmlDocument();doc.LoadXml(Encoding.UTF8.GetString(ms.ToArray()));if (doc.DocumentElement != null){return doc.DocumentElement.InnerXml;}else{return o.ToString();}}/// <summary>/// 设置WEB请求/// </summary>/// <param name="request"></param>private static void SetWebRequest(HttpWebRequest request){request.Credentials = CredentialCache.DefaultCredentials;request.Timeout = 10000;}/// <summary>/// 设置请求数据/// </summary>/// <param name="request"></param>/// <param name="data"></param>private static void WriteRequestData(HttpWebRequest request, byte[] data){request.ContentLength = data.Length;Stream writer = request.GetRequestStream();writer.Write(data, 0, data.Length);writer.Close();}/// <summary>/// 获取字符串的UTF8码字符串/// </summary>/// <param name="Pars"></param>/// <returns></returns>private static byte[] EncodePars(Hashtable Pars){return Encoding.UTF8.GetBytes(ParsToString(Pars));}/// <summary>/// 将Hashtable转换成WEB请求键值对字符串/// </summary>/// <param name="Pars"></param>/// <returns></returns>private static String ParsToString(Hashtable Pars){StringBuilder sb = new StringBuilder();foreach (string k in Pars.Keys){if (sb.Length > 0){sb.Append("&");}sb.Append(HttpUtility.UrlEncode(k) + "=" + HttpUtility.UrlEncode(Pars[k].ToString()));}return sb.ToString();}/// <summary>/// 获取Webservice响应报⽂XML/// </summary>/// <param name="response"></param>/// <returns></returns>private static XmlDocument ReadXmlResponse(WebResponse response){StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.UTF8);String retXml = sr.ReadToEnd();sr.Close();XmlDocument doc = new XmlDocument();doc.LoadXml(retXml);return doc;/// 设置XML⽂档版本声明/// </summary>/// <param name="doc"></param>private static void AddDelaration(XmlDocument doc){XmlDeclaration decl = doc.CreateXmlDeclaration("1.0", "utf-8", null);doc.InsertBefore(decl, doc.DocumentElement);}}以上是在不引⽤WEB服务的条件下动态调⽤WEB服务⽅法,如果该服务地址不确定或后期有可能会变动,则采⽤上述这些⽅法会⽐较好,当然如果服务地址不会出现变更的情况下,可以在VS中直接引⽤WEB服务,然后就可调⽤⾃动⽣成的SOAPClient类来调⽤相应的WEB服务⽅法,这样就简单很多,如下:avar client = new SmsService.wmgwSoapClient(); //wmgwSoapClient就是引⽤WEB服务后⾃动⽣成的类string result = client.MongateSendSubmit(tuserId.Text, tpassword.Text, tpszMobis.Text, tpszMsg.Text, int.Parse(tiMobiCount.Text),tpszSubPort.Text, tMsgId.Text);。
gsoap使用小结gSoap使用小结分类:开发路上的点点滴滴 2012-03-30 11:33 3564人阅读评论(2) 收藏举报webservicesoapauthorizationnull工具c下载gSoap1.下载完成后直接解压缩,在目录gsoap-2.8\gsoap\bin下面有编译工具,支持多个平台,我们使用的是win32平台的工具wsdl2h.exe 解析WebService的wsdl文件soapcpp2.exe 编译WebService代码2.接下来需要先获得WebService的wsdl文件,访问WebService时,http://XXXX/XXXX.asmx?wsdl这个地址就是需要的wsdl文件,选择查看源文件,然后另存为的方式,获取到wsdl文件,例如:另存为webs.wsdl文件。
3.解析wsdl文件执行wsdl2h.exe -o webs.wsdl命令,就会生成一个webs.h的头文件这里简单说一下参数,主要常用的是-o和-c,-o后面跟的文件名是需要生成的文件名。
-c表示生成纯C的头文件,否则默认是C++。
具体参数可以运行wsdl2h.exe /?查看帮助。
4.编译执行soapcpp2.exe webs.h,会生成很多个文件,这里同样可以加一些参数,具体不解释了,可以通过soapcpp2.exe /?命令来查看。
我们找出需要的以下几个文件:soapC.cppsoapClient.cppsoapH.hsoapStub.hWebsSoap.nsmap再加上另外两个文件(不在bin目录下,在gsoap-2.8\gsoap目录下):stdsoap2.hstdsoap2.cpp一共7个文件,就是我们最终访问WebService所需要的soap访问调用文件。
这里是C++的代码,根据需要,也可以生成C的代码,stdsoap2.cpp更换为stdsoap2.h文件。
把上述7个文件,加入到自己的工程中编译即可,接下来就是如何调用的问题了。
C++通过gSoap访问webService 最近在wince机器上做一个了项目要求访问wcf服务,看了一些资料了解到可以通过gsoap实现。
刚刚弄通了,写个小结日后回顾,有需要的也可以看看。
1、下载最新gsoap包(/projects/gsoap2/),下载完解压就可以了。
2、运行“cmd” 进入“gsoap-2.8\gsoap\bin\win32”目录下。
3、生成头文件。
wsdl2h -o WSCheckQqOnline.h/webservices/qqOnlineWebService.asmx?WSDL (转注:关于gSoap及它的两个工具:soapcpp2和wsdl2h的介绍,可以参考:/guxch/article/details/8332701)4、将“\gsoap-2.8\gsoap\import”目录下的soap12.h 和stlvector.h复制到“gsoap-2.8\gsoap\bin\win32”中。
生成代码的时候要用到。
5、生成webService要调用的代码。
我所使用的是“soapcpp2-C -L -i -x WSCheckQqOnline.h”。
-C:仅生成客户端代码-S :仅生成服务器端代码-L :不要产生soapClientLib.c和soapServerLib.c文件-c :产生纯C代码,否则是C++代码(与头文件有关)-I :指定import路径(见上文)-x :不要产生XML示例文件-i :生成C++包装,客户端为xxxxProxy.h(.cpp),服务器端为xxxxService.h(.cpp)6、新建一个工程,将下列文件复制到工程中去。
7、在“\gsoap-2.8\gsoap”目录下找到stdsoap2.cpp 和stdsoap2.h 也复制到工程中去。
8、vs中的目录结构:9、不使用预编译头,选中这三个文件:属性—>c/c++—>预编译头—>不使用预编译头:10、测试代码:#include "qqOnlineWebServiceSoap.nsmap"#include "soapqqOnlineWebServiceSoapProxy.h"#include <string>#include <iostream>int main(){// 传入服务地址qqOnlineWebServiceSoapProxy proxy("/webservices/qqOnlineWebService.asmx");// 要调用的接口_ns1__qqCheckOnline qqCheck;qqCheck.soap = &proxy;std::string qqCode("253786989");qqCheck.qqCode = &qqCode;_ns1__qqCheckOnlineResponse response;proxy.qqCheckOnline(&qqCheck, &response);std::cout << *response.qqCheckOnlineResult << std::endl;return 0;}11、运行结果:。
gsoap使用方法及心得(一)gSOAP是一个夸平台的,用于开发Web Service服务端和客户端的工具,在Windows、Linux、MAC OS和UNIX下使用C和C++语言编码,集成了SSL功能。
下载地址:官方网站:对于Windows平台下开发客户端,首先下载最新的gsoap_win32_2.7.6c.zip包,具体在以下地址:/sourceforge/gsoap2 /gsoap_win32_2.7.6c.zip首先查看gsoap的User's Guide,基本就能对gsoap有个全面的了解,通过阅读Sample里的例子程序深入。
然后搜索网上其它一些文章,比如:gSOAP简单多线程服务器程序:纯c的gSoap实现WebService:/2sky2sea/blog/item/40ec5555680279c1b74 5ae9b.html我以网上出现的实现一个简单的加法函数为例,讲讲我在操作过程中遇到的问题。
一、服务器端1、首先编写 add.h文件://gsoap ns service name: add//gsoap ns service namespace: http://localhost/add.wsdl//gsoap ns service location: http://localhost//gsoap ns service executable: add.cgi//gsoap ns service encoding: encoded//gsoap ns schema namespace: urn:addint ns__add( int num1, int num2, int* sum );2、用gsoap/bin目录下的soapcpp2.exe程序,生成一些文件。
可以把soapcpp2.exe拷贝到一add.h目录下,用cmd执行soapcpp2.exe add.h。
在这个目录下会自动生成许多将来有用的文件,如add.namap,soapH.h,soapC.cpp,soapClient.cpp,soapServer.cpp等文件。
gSoap工具处理wsdl文件
作者:杨建安审校:陈泓希适用版本:Teamcenter
在teamcenter实施过程中,通过流程驱动,实现与其它系统的对接越来越常见。
对接方式中,客户端调用webservice的方式最为被大家接受认可,其通用性、稳定性、安全性都得到过验证。
因此掌握好客户端调用webservice的方式势在必行。
调用webservice的关键是如何将wsdl(web服务的描述文件)解析成xx.h及xx.cpp文件。
1.下载gSoap工具包;
2.切换到win32文件夹下;
1
2
图1
3.在win32目录下执行wsdl2h,生成wsdl 文件的头文件;
图2
4.在win32目录下执行soapcpp2,
根据刚刚生成的头文件生
成客户端调用的依赖文件。
图3
图4
以上就是生成调用webservice客户端相关依赖的具体步骤。
3。
用gsoap实现面向Java客户端的WebService2012-02-17 18:20用gsoap实现面向Java客户端的WebService环境操作系统:Windows 7gsoap版本:2.8.6axis2版本:1.6.1C++编译器/开发环境:Visual Studio 2008JDK版本:1.6.0_22ant版本:1.7.0一、简单示例利用gsoap和axis,常规的WebService(C++实现)以及java访问客户端的开发过程为:第一步:编写一个头文件,定义WebService中使用的数据类型和消息,例如:示例1:add.h,一个实现简单的加法运算的服务//gsoap ns service name: add//gsoap ns service namespace: http://localhost/add.wsdl//gsoap ns service location: http://localhost//gsoap ns service executable: add.cgi//gsoap ns service encoding: encoded//gsoap ns schema namespace: urn:addint ns__add( int num1, int num2, int* sum);示例2:array.h,返回一个使用复杂数据结构为元素的数组的服务//gsoap ns service name:ArrayDemo//gsoap ns service namespace: http://localhost/add.wsdl //gsoap ns service location: http://localhost//gsoap ns service executable: ArrayDemo.cgi//gsoap ns service encoding: encoded//gsoap ns schema namespace: urn:ArrayDemoclassns3__NVElement {public:int ID;char *name;char *value;};class NVSet {public:ns3__NVElement *__ptr; // points to array elementsint __size; // number of elements pointed toNVSet();~NVSet();void print();};int ns__getAllNamedValues(NVSet &return_);注意ns和ns3这样的前缀后面都是两个下划线,这是gsoap的约定,前缀ns和ns3都是命名空间。
用gSOAP调用Web Services1、配置gSOAP从/project/showfiles.php?group_id=52781 下载gSOAP,解压后在gsoap\bin\win32里找到wsdl2h.exe 和soapcpp2.exe程序。
通过这两个程序可以生成客户端需要的C/C++文件。
这两个程序的使用方法:wsdl2h.exe: 编译wsdl文件生成c/c++头文件-o 文件名,指定输出头文件-n 名空间前缀代替默认的ns-c 产生纯C代码,否则是C++代码-s 不要使用STL代码-t 文件名,指定type map文件,默认为typemap.dat-e 禁止为enum成员加上名空间前缀soapcpp2.exe: gSOAP编译器,编译头文件生成服务器和客户端都需要的c/c++文件(如果使用STL,需要从压缩包里找到stlvector.h放到soapcpp2.exe目录下,否则运行失败)-C 仅生成客户端代码-S 仅生成服务器端代码-L 不要产生soapClientLib.c和soapServerLib.c文件-c 产生纯C代码,否则是C++代码(与头文件有关)-I 指定import路径(见上文)-x 不要产生XML示例文件-i 生成C++包装,客户端为xxxxProxy.h(.cpp),服务器端为xxxxService.h(.cpp)我写了个批处理:wsdl2h -o xxxService.h "WSDL文件URL"soapcpp2 -C xxxService.h如果是asmx,可以在URL后加"?WSDL" 来获取WSDL文件,它是一个XML,用来描述接口,它是与语言无关的,类似COM的IDL文件。
2、创建VC工程,把生成的文件拷到工程目录生成的文件有:soapStub.h 从输入Header 文件生成的经过修改且带标注的Header 文件soapH.h 主Header 文件,所有客户机和服务源代码都要将其包括在内soapC.c 指定数据结构的序列化器和反序列化器soapClient.c 远程操作的客户机存根例程stdsoap2.h stdsoap2.cpp 运行时库的Header 文件stdsoap2.cpp 运行时C++ 库,带XML 解析器和运行时支持例程创建一个控制台工程:把上面的几个文件加到工程;为soapC.c、soapClient.c 和stdsoap2.cpp 选择Not using precompiled headers,因为它们并不依赖于stdafx.h。
加入wsock32.lib库,这时编译会出现_namespace错误,包含两个文件就可以:#include "soapServiceSoapProxy.h"#include "ServiceSoap.nsmap"3、调用Web服务:比如服务有个String getContext(string userName); 接口,我们要怎么调用它:string username = "heng" ;_ns1__getContext getContext ; // 调用接口_ns1__getContextResponse getContextResponse ; // 用来接收返回值struct soap soap;soap_init(&soap);erName = &username ; // 传入string userNameusing namespace std; 大功造成!int result = soap_call___ns2__getContext(&soap, NULL, NULL, &getContext, &getContextResponse ) ;if(result == SOAP_OK){cout<<"Result:"<<getContextResponse.getContextResult->c_str()<<endl; // 查看返回值}else{cout<<"Fail!"<<endl;}补充,因为用到STL,再加上#include <string>另一个版本的!(基于gsoap-win32-2.7版本,编译环境为VS2005)客户端访问自己定义的一个WebService(命名为AddService,对输入的两个整形参数求和,具体服务定义参见AddService.wsdl)转换WSDLwsdl2h.exe -s -o AddService.h AddService.wsdl生成具体调用代码在命令行输入soapcpp2.exe -C AddService.h生成代码后,AddService.h就没有用了,不用加入到工程中。
生成的文件soapStub.hsoapAddServiceSoapBindingProxy.h:封装了调用webservice的类soapH.hsoapClientLib.cpp:用不到soapClient.cppsoapC.cppAddServiceSoapBinding.nsmap:namespaces声明,需要包含在一个cpp文件里面,比如放在StdAfx.cpp里面,否则连接时报错:unresolved external symbol _namespaces还需要stdsoap2.cpp和stdsoap2.h文件,在gsoap-2.7soapcpp2目录下。
注意:#include “StdAfx.h”加到第一行,否则VC编译报错:fatal error C1010: unexpected end of file while looking for precompiled header directive实际调用代码将这些文件加入到C++工程中,可以使用以下代码调用WebService:头文件// 包含代理类的头文件#include "gSoap\soapAddBindingProxy.h"声明访问代理对象AddBinding serviceBinding;设置访问的WebServiceURLserviceBinding.endpoint = ("http://LocalHost:8082/");调用接口int iResult;nRetCode = serviceBinding.__ns1__AddOperation(12, 22,iResult);服务端实现AddService(对输入的两个整形参数求和)生成调用代码同客户端生成方法基本一致。
需要注意的是以下几点:由.h文件生成具体调用代码:soapcpp2.exe -S AddService.hsoapClient.cpp soapClientLib.cpp soapServerLib.cpp这三个文件不需要加入到C++工程中。
实现服务线程在程序开始时,启动服务线程。
UINT GSoapServiceThreadFunc(LPVOID p){...}定义编码格式// 设置UTF-8编码方式soap_set_mode(&soap, SOAP_C_UTFSTRING);设置服务的端口号代码// 端口号int port = 8083;int backlog = 100; //int m = soap_bind(&soap, NULL, port, backlog);if(m < 0){strOutput.Format(_T("GSoapServiceThreadFunc——在端口%d上启动服务失败!"), port);OutputDebugString(strOutput);soap_done(&soap); // close master socket and detach environmentexit(-1);}设置超时soap.accept_timeout = 5;// 设置GSoap连接超时,单位:秒创建循环,监听,如果有新连接进来则创建请求处理现场代码while(TRUE){if( WaitForSingleObject(g_eventTerminateService.m_hObject, 0) == WAIT_OBJECT_0 )// 结束GSoap服务线程{break;}int s = soap_accept(&soap);if( !soap_valid_socket(s) ){if( soap.errnum ){soap_print_fault(&soap, stderr);soap_done(&soap); // close master socket and detach environmentexit(1);}strOutput.Format(_T("\nGSoapServiceThreadFunc——等待客户端连接超时!"));OutputDebugString(strOutput);}else{strOutput.Format(_T("\n收到来自于IP地址%d.%d.%d.%d的socket连接%d!"), (soap.ip >> 24)&0xFF, (soap.ip >> 16)&0xFF, (soap.ip>> 8)&0xFF, soap.ip&0xFF, s);OutputDebugString(strOutput);struct soap* tsoap = soap_copy(&soap); // make a safe copyif( !tsoap ){break;}AfxBeginThread(process_request, tsoap);}}实现请求处理线程相应代码代码/// GSoap请求处理线程UINT process_request(LPVOID soap){CoInitialize(NULL); soap_serve((struct soap*)soap); // 会自动调用具体的接口函数soap_destroy((struct soap*)soap); // dealloc C++ datasoap_end((struct soap*)soap); // dealloc data and clean upsoap_done((struct soap*)soap); // detach soap structfree(soap); CoUninitialize(); return 0;}实现接口功能函数在代码中定义相应的接口功能函数int __ns1__AddOperation(struct soap*, int A, int B, int&result){result = A + B;return SOAP_OK;}函数原型在soapStub.h中定义代码/*************************************************** ***************************\*** Service Operations***\*************************************************** ***************************/SOAP_FMAC5 intSOAP_FMAC6 __ns1__AddOperation(struct soap*, int A, int B,int &result);现在采用的是默认的命名空间前缀,可以使用typemap.dat 文件赋予自定义的命名空间。