gSOAP学习笔记

网站:http://www.cppblog.com/pansunyou/archive/2013/08/05/137563.html

gSOAP学习笔记

虽然SOAP被有些人说太老土,但在银行里仍有大量系统在使用,前段时间在工作中接触到,故记录一下。

gSOAP学习笔记

潘孙友 2010-12-27 于遵义

目录
一、基本概念1.1 关于SOAP1.2 关于gSOAP1.3 gSOAP编译器(命令行工具)1.3.1 wsdl2h1.3.2 socapcpp2
二、gSOAP开发:Web Service服务端
三、gSOAP开发:Web Service客户端
四、参考资料笔记中的代码

一、基本概念

1.1 关于SOAP

SOAP(Simple Object Access Protocol),即简单对象访问协议,是在分布式的环境中交换数据的简单协议,以XML作为数据传送语言。 SOAP有两种工作模式,一种是RPC(Remote Procedure Call),另一种是Message-Oriented。MO可以利用XML来交换结构更复杂的数据。RPC模式的SOAP可以理解为这样一个开发协议:SOAP=RPC+HTTP+XML,具有以下特点:

  • 采用HTTP作为通信协议,采用客户/服务模式;
  • RPC作为统一的远程方法调用途径;
  • 传送的数据使用XML格式。

看一个简单的请求及回复SOAP数据(真实数据):

POST /wpsoap/ HTTP/1.1
Host: 127.0.0.1:10240
User-Agent: gSOAP/2.7
Content-Type: text/xml; charset=utf-8; action=""
Content-Length: 480
Connection: close
SOAPAction: ""<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope 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:ns1="http://www.example.org/wpsoap/" xmlns:ns2="urn:nszfpt"><SOAP-ENV:Body><ns2:login><req><username>admin</username><password>3.14159</password></req></ns2:login></SOAP-ENV:Body></SOAP-ENV:Envelope>
HTTP/1.1 200 OK
Server: gSOAP/2.7
Content-Type: text/xml; charset=utf-8; action=""
Content-Length: 555
Connection: close<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope 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:wpsoap="urn:nszfpt"><SOAP-ENV:Body SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><wpsoap:tagRspLogin><rsp><retCode>0</retCode><retMessage>login ok!</retMessage></rsp><session>01234567890</session></wpsoap:tagRspLogin></SOAP-ENV:Body></SOAP-ENV:Envelope>

这东西非常的复杂,我仅仅记录一下使用到的部分。

1.2 关于gSOAP

引用:http://blog.csdn.net/darkone/archive/2006/12/14/1442525.aspxgSOAP编译工具提供了一个SOAP/XML 关于C/C++ 语言的实现,从而让C/C++语言开发web服务或客户端程序的工作变得轻松了很多。绝大多数的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的解释器及导入器可以使用户不需要分析web服务的细节就可以实现一个客户端或服务端程序。

照我理解,gSOAP可以为我们生成soap服务器端+客户端代码的框架,我们只需实现具体的接口函数即可。而生成代码的工具就是上面文中提到的“gSOAP编译器”。

1.3 gSOAP编译器(命令行工具)

1.3.1 wsdl2h

此工具用来从WSDL文件生成c/c++头文件。

wsdl2h -o 头文件名 WSDL文件名或URL
常用的其它参数:
-o 文件名,指定输出头文件
-n 名空间前缀 代替默认的ns
-c 产生纯C代码,否则是C++代码
-s 不要使用STL代码
-t 文件名,指定type map文件,默认为typemap.dat
-e 禁止为enum成员加上名空间前缀

1.3.2 socapcpp2

此工具用来从头文件,生成SOAP服务器及客户端代码,还包括WSDL、测试用XML数据。

soapcpp2 头文件
常用选项
-C 仅生成客户端代码
-S 仅生成服务器端代码
-L 不要产生soapClientLib.c和soapServerLib.c文件
-c 产生纯C代码,否则是C++代码(与头文件有关)
-I 指定import路径(见上文)
-x 不要产生XML示例文件
-i 生成C++包装,客户端为xxxxProxy.h(.cpp),服务器端为xxxxService.h(.cpp)。

二、gSOAP开发:Web Service服务端

开发服务器程序,需使用gSOAP生成服务器端代码框架。我们有两种做法:

  1. 编写WSDL,使用wsdl2h生成头文件,再soapcpp2生成框架代码;
  2. 编写头文件,使用soapcpp2生成框架代码;

这两种方式,结果是一样的,最终都有产生头文件,并生成代码。不同在于,在项目的开发中需要维护的文件不同,前者是需要维护WSDL文件,后者维护头文件。

我个人觉得第二种方式更好用,不仅仅是少了个步骤,而是WSDL的语法太难写了,有点XSD的味道。而头文件的编写,更接近于程序员的思考方式,比如定义消息结构,定义接口名称等。

gSOAP是非常智能的,它利用C/C++的注释来获取信息,所以在手工编写的头文件中,注释是用用处的,常以// gsoap 名字空间 …开头。做为学习,我准备为php blog程序wordpress写一个web service接口,名字叫wpsoap。

我开始写头文件(wpSoap.h)了,出于学习目的,我仅实现了两个接口:一是用户登陆;一是日志发布。

/*** @file wpsoap.h* @brief 为wordpress2.7提供web service接口**  "//gsoap"开头行,请勿删除.* *  1. 通过此文件生成WSDL 及 服务端代码* *    >mkdir -p srvSrcFromH*    >cd srvSrcFromH*    >soapcpp2 -L -S "wpsoap.h" -I /path/to/gsoap-2.8/gsoap/import/* *  2. 通过WSDL生成客户端代码* *    >mkdir -p clientSrcFromWSDL*    >cd clientSrcFromWSDL*    >wsdl2h.exe  -o wpsoap.h ../srvSrcFromH/wpsoap.wsdl -I /path/to/gsoap-2.8/gsoap/import/*    >soapcpp2 -L -C wpsoap.h -I /path/to/gsoap-2.8/gsoap/import/** @author pansunyou@gmail.com* @version 1.0* @date 2010-12-27
*///gsoap wpsoap service name: wpsoap
//gsoap wpsoap service namespace: http://www.example.org/wpsoap/
//gsoap wpsoap service location: http://192.168.0.187:10240/wpsoap/
//gsoap wpsoap service encoding: encoded
//gsoap wpsoap schema namespace: urn:nszfpt#import "stlvector.h"//通用回复
class wpsoap__tagCommResponse
{int			retCode		;      //回复码std::string retMessage	;      //回复消息
};//[请求]用户登陆
class wpsoap__tagReqLogin
{std::string username        ;      //用户名std::string password        ;      //密码名文
};//[答复]用户登陆
class wpsoap__tagRspLogin
{wpsoap__tagCommResponse rsp	 ;      //通用回复std::string session       ;      //会话标识
};//[接口]登陆接口
int wpsoap__login(wpsoap__tagReqLogin req, wpsoap__tagRspLogin& rsp);//[请求]发布日志
class wpsoap__tagReqPost
{std::string title			  ;      //标题std::string body              ;      //正文
};//[答复]发布日志
class wpsoap__tagRspPost
{wpsoap__tagCommResponse rsp    ;      //通用回复
};//[接口]发布日志接口
int wpsoap__post(wpsoap__tagReqPost req, wpsoap__tagRspPost& rsp);

在接口中,我使用到了自定义的消息结构wp_soap_tag*,这里的wpsoap__前缀是必须的,这样soapcpp2才能为我们生成正确的代码。

之后,我使用soapcpp2生成服务端代码框架:

@echo off
@set path=%cd%\..\..\contrib\gsoap-2.8\gsoap\bin\win32\;%path%mkdir srvSrcFromH 2>nul
cd srvSrcFromH
soapcpp2.exe -L -S ..\res\wpSoap.h -I ..\..\..\contrib\gsoap-2.8\gsoap\import\
pause

要编译出服务程序,有这些代码还不够,还需要自己写两个文件,一个用来写main函数,一个用来写wpsoap的接口函数(当然可以放在一个文件里)。最终我的服务器程序有以下文件:(另外,还需要gsoap目录下的stdsoap2.cpp,因为我把它编译为静态库了,所以这里没列出来。)

D:\wpSoapServer
|   makeSrc.bat
|   wpsoapimpl.cpp                //这里实现了soapStub.h给出的接口
|   wpsoapsrv.cpp                  //这里是main函数开始的地方
+---res
|       wpSoap.h
\---srvSrcFromHsoapC.cppsoapH.hsoapServer.cppsoapStub.hsoapwpsoapObject.hwpsoap.login.req.xmlwpsoap.login.res.xmlwpsoap.nsmapwpsoap.post.req.xmlwpsoap.post.res.xmlwpsoap.wsdlwpsoap.xsd

每次我修改了res/wpSoap.h后,我就运行一下makeSrc.bat,自动重新生成srvSrcFromH目录里的所有东西,并且这个目录里的所有代码是不需要手工维护的(除非有特殊需要)。

在服务器代码中,我仅实现了以下两个函数(wpsoapimpl.cpp):

int wpsoap__login(struct soap*, wpsoap__tagReqLogin req, wpsoap__tagRspLogin &rsp);
int wpsoap__post(struct soap*, wpsoap__tagReqPost req, wpsoap__tagRspPost &rsp);

wpsoapsrv.cpp里的代码仅仅是调用gSOAP产生的代码来建立socket服务器,基本不需维护。gSOAP是线程安全的,可以将请求分配到线程池内实现高效服务,但我仅为了走通gSOAP的使用流程,没有这样使用。

具体做法可以参考:http://www.cs.fsu.edu/~engelen/soapdoc2.html

三、gSOAP开发:Web Service客户端

客户端代码本来也是可以通过为服务端编写的头文件生成的,但是为了真实一点,假设我无法获取服务器开发时使用的头文件,仅仅有个公开的WSDL文件,就是上面产生的srvSrcFromH /wpsoap.wsdl。

我用这个脚本来生成客户端框架代码:

@echo off
@set path=%cd%\..\..\contrib\gsoap-2.8\gsoap\bin\win32\;%path%mkdir clientSrcFromWSDL 2>nul
cd clientSrcFromWSDL
wsdl2h.exe -o wpsoap.h ..\..\wpSoapServer\srvSrcFromH\wpsoap.wsdl
soapcpp2.exe -L -C wpsoap.h -I ..\..\..\contrib\gsoap-2.8\gsoap\import\
pause

加上我测试用的代码wpsoapclient.cpp,以及gosap目录里的stdsoap2.cpp,我有了如下文件:

D:\wpSoapClient
|   makeSrc.bat
|   wpsoapclient.cpp
\---clientSrcFromWSDLsoapC.cppsoapClient.cppsoapH.hsoapStub.hsoapwpsoapProxy.hwpsoap.hwpsoap.login.req.xmlwpsoap.login.res.xmlwpsoap.nsmapwpsoap.post.req.xmlwpsoap.post.res.xml

客户端代码非常少(仅仅是实现,容错之类的都未考虑):

/*** @file wpsoapclient.cpp* @brief 访问wpsoap服务** 调用wpsoap的客户端示例代码** @author pansunyou@gmail.com* @version 1.0* @date 2010-12-27
*/#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <cstdlib>
#include <string>
#include "clientSrcFromWSDL/soapStub.h"
#include "clientSrcFromWSDL/soapwpsoapProxy.h"
#include "clientSrcFromWSDL/wpsoap.nsmap"using namespace std;int main(int argc, char*argv[])
{wpsoap wpsoapClient;if (argc==2)wpsoapClient.endpoint = argv[1];//1. 登陆string username = "admin";string password = "3.14159";int r = 0;ns2__tagReqLogin req;req.username = username;req.password = password;_ns2__login ns2__login;ns2__login.req = &req;_ns2__tagRspLogin rsp;r = wpsoapClient.__ns1__login(&ns2__login, &rsp);if (r!=0){fprintf(stderr, "调用soap接口失败!\n");return -1;}if (0!=rsp.rsp->retCode){printf("登陆失败 retCode=%d, retMessage=%s\n",rsp.rsp->retCode, rsp.rsp->retMessage.c_str());return -1;}printf("登陆成功! [session=%s]\n",rsp.session.c_str());ns2__tagReqPost reqPost;reqPost.body = "post article by wpsoap!";reqPost.title = "hello, wpsoap!";_ns2__post ns2__post;ns2__post.req = &reqPost;_ns2__tagRspPost ns2__tagRspPost;r = wpsoapClient.__ns1__post(&ns2__post, &ns2__tagRspPost);if (r!=0){fprintf(stderr, "调用soap接口失败!\n");return -1;}if (0!=rsp.rsp->retCode){printf("发布日志失败 retCode=%d, retMessage=%s\n",rsp.rsp->retCode, rsp.rsp->retMessage.c_str());return -1;}printf("日志发布成功! [retMessage=%s]\n", rsp.rsp->retMessage.c_str());return 0;
}

四、参考资料

http://gsoap2.sourceforge.net/
http://www.cppprog.com/2009/0723/138.html

http://hi.baidu.com/winnyang/blog/item/d5fd4f3df38f35cd9e3d625b.html 
http://www.cs.fsu.edu/~engelen/soap.html
http://tangentsoft.net/mysql++/


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/462355.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Scala实践6

1 if表达式 Scala中if...else..表达式是有返回值的&#xff0c;如果if和else返回值类型不一样&#xff0c;则返回Any类型。scala> val a310 a3: Int 10scala> val a4 | if(a3>20){ | "a3大于a4" | }else{ | "a4大于a3" | } a4: String a4大于a…

jquery ui autocomplete输入中文不自动完成的问题

因为输入法或浏览器的问题&#xff0c;在输入中文后并没有触发自动完成&#xff0c;要再按多一下键盘才触发&#xff0c;查看发现它是用keydown来实现.bind("keydown.autocomplete", function(event) {....})可以对其input事件进行监听来解决问题&#xff0c;在上面的…

【洛谷p1464】 Function

中考第一天&#xff1b; 感觉我超废&#xff1b; 就是看这道题特别顺眼emmm SOLUTION&#xff1a; 思路的话是开三维数组s[i][j][k]&#xff0c;先三重for循环预处理出s[0~20][0~20][0~20]的w(a,b,c)&#xff0c;然后直接搜索就好了。 Code&#xff1a; #include<bits/stdc.…

一个简单的高并发的回应服务器(5万并发)

一个简单的高并发的回应服务器&#xff0c;主要是使用boost的库&#xff01; 自己测试过可以达到5万个并发&#xff01; 程序的下载地址&#xff1a;http://download.csdn.net/detail/guanyijun123/8335907 #include <stdio.h> //#include "AuthenHandle.h" /…

delphi 的一些备忘

override&#xff1a;覆盖&#xff1b; overload&#xff1a;重载&#xff1b; Reintroduce&#xff1a;重定义&#xff0c;它的引入是为了屏蔽父类的一个虚方法,而在子类中生成一个新的方法; 其实你不使用reintroduce也会覆盖屏蔽父类的方法的但是会产生一个警告&#xff01; …

10.高效分布

ListView默认的分页是先从数据源取得所有数据&#xff0c;然后再截取当前页面的部分&#xff0c;在数据量非常大的情况下效率非常低&#xff0c;因此默认的分布基本不能用。应该是只从数据源取得要显示的数据即可。SQL中语句中取得分页数据的方法为&#xff1a;Select * ,ROW_N…

项目测试~

这个作业属于哪个课程 https://edu.cnblogs.com/campus/xnsy/SoftwareEngineeringClass2 这个作业要求在哪里 https://edu.cnblogs.com/campus/xnsy/SoftwareEngineeringClass2/homework/3340 团队名称 求莫名堂 作业的目标 学会进行项目的测试&#xff0c;并通过测试发…

boost_1_48_0 在VS2008下的安装 Boost.Asio安装

第一步&#xff1a;到官网www.boost.org&#xff0c;下载boost最新版boost_1_48_0.zip第二步&#xff1a;将boost压缩包解压到C盘根目录下(在C盘操作简单&#xff0c;不会出错)&#xff0c;目录为C:\BOOST_1_48_0,里面就是boost的源码和需要编译的文件及文档资料第三步&#xf…

线程----BlockingQueue

import java.util.concurrent.ArrayBlockingQueue;import java.util.concurrent.BlockingQueue;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;/** 本例介绍一个特殊的队列:BlockingQueue,如果BlockQueue是空的,从BlockingQueue取东西…

D3D9 effect (hlsl)(转)

转:http://blog.csdn.net/leonwei/article/details/8212800 effect其实整合了shader和render state的控制两大部分内容 9.1 effect文件基本框架 part1 &#xff1a;shader state包括全局变量 shader数据结构定义&#xff0c;shader的实现 part2 &#xff1a;texture and sample…

boost_1.47在VS2010下的安装

第一步&#xff1a;到官网www.boost.org&#xff0c;下载boost最新版boost_1_47_0.zip第二步&#xff1a;将boost压缩包解压到C盘根目录下(在C盘操作简单&#xff0c;不会出错)&#xff0c;目录为C:\BOOST_1_47_0,里面就是boost的源码和需要编译的文件及文档资料第三步&#xf…

创建 WPF 不规则窗口

创建 WPF 不规则窗口 本文为khler原作&#xff0c;转载必须确保本文完整并完整保留原作者信息及本文原始链接  E-mail: khler163.com  QQ: 23381103  MSN: pragmachotmail.com   相对于用MFC创建不规则窗口&#xff0c;WPF创建不规则窗体的过程就显得相当享受了&…

公司运作 - 利润率、周转率

公司一般由市场部、研发部、财务部、人力资源部及其他辅助部门组成。分成了几个层面&#xff0c;如下&#xff1a; 宏观层面&#xff1a;业务范围、业务定位、专业化、多元化部门层面&#xff1a;各部门绩效、部门职责主体层面&#xff1a;跨部门事务&#xff0c;如产品研发涉及…

ffmpeg编解码详细过程

1. 注册所有容器格式和CODEC:av_register_all() 2. 打开文件:av_open_input_file() 3. 从文件中提取流信息:av_find_stream_info() 4. 穷举所有的流&#xff0c;查找其中种类为CODEC_TYPE_VIDEO 5. 查找对应的解码器:avcodec_find_decoder() 6. 打开编解码器:avcodec_open() 7.…

使用docker 起容器配置负载均衡(加权)

首先要准备三个nginx的容器&#xff1b; 第二个容器&#xff1a; 第三个容器&#xff1a; 进入第一个容器&#xff08;主容器&#xff09; 要配置的容器&#xff08;docker exec -it 容器id /bin/bash&#xff09; vi/etc/nginx/nginx.conf 修改配置 在http{ }中加入 vi/etc/…

茴香豆的n种写法之②——Sql据多个条件 查询每个条件的前N条记录

----------------------------------- Author: liangCK 小梁-- Title : 查每个分组前N条记录-- Date : 2008-11-13 17:19:23-----------------------------------> 生成测试数据: #TIF OBJECT_ID(tempdb.dbo.#T) IS NOT NULL DROP TABLE #TCREATE TABLE #T (ID VARCHAR(3),G…

PostgreSQL建表动作分析

首先&#xff0c;建立表&#xff1a; pgsql# create table tab10(id integer); CREATE TABLE pgsql# select 147525::regclass;regclass ----------tab10 (1 row)pgsql# 查看此时的文件信息&#xff1a; [pgsqllocalhost 16384]$ pwd /home/pgsql/DemoDir/base/16384[pgsqllo…

http 断点续传,Windows下HTTP方式单线程下载

http 断点续传www.diybl.com 时间 &#xff1a; 2011-05-20 作者&#xff1a;匿名 编辑&#xff1a;hawk 点击&#xff1a; 1128 [ 评论 ]-- 原理&#xff1a; 1. 打开本地文件fopen&#xff0c;移动文件指针到文件尾fseek 2. 获得文件大小ftell, 格式化HTTP请求头 &…

给创业者的30条建议

http://www.cocoachina.com/programmer/20150206/11119.html 去年年底的时候&#xff0c;我&#xff08;Firstround Review 主编&#xff09;在 Facebook 公司的咖啡厅里和 Caryn Marooney 交流着创业公司应该注意些什么事情。Caryn Marooney 现在是 Facebook 公司科技交流部门…

php swoole websocket vue 实现聊天室案例

代码地址: https://github.com/9499574/demo_chat_room 转载于:https://www.cnblogs.com/phper8/p/11017892.html