,,C++中gSOAP的使用详解

,,C++中gSOAP的使用详解

本文主要介绍了gSOAP在c中的详细使用说明,边肖觉得挺好的。现在分享给大家,给大家一个参考。来和边肖一起看看吧。

目录

soap头文件构建客户端应用生成SOAP源代码构建客户端项目构建服务器应用生成SOAP源代码构建服务器项目打印消息SOAP测试项目源代码摘要本文主要介绍了g SOAP在C中的用法,并介绍了SOAP协议的基础知识,适合初次使用g SOAP的开发人员使用。gSOAP官网上的样例代码有些错误,对第一次接触的人不太友好。本文在官方示例calc的基础上做了一些补充和改动。

SOAP简介

SOAP是一个简单的基于 XML 的协议,使得应用程序通过 HTTP 来交换信息。详情请参考SOAP教程。SOAP的本质是通过HTTP协议交换XML格式的数据,但是这种XML格式的定义是被普遍接受的。

使用SOAP时,需要注意的是,由于版本不同(如soapevn、SOAP-ENV),SOAP的XML命名空间可能会有所不同。最好在调用SOAP服务之前确认服务器的XML格式。

gSOAP

gSOAP有两个版本:商业版和开源版。开源版使用GPLv2开源协议,支持多种操作系统。详情请参考github或官网。

GSOAP提供了一套编译工具(可以认为是代码生成器)和一些库文件,以简化用C/C语言开发web服务或客户端程序的工作。开发人员可以专注于实现应用程序的逻辑:

编译器提供了C/C语言的SOAP/XML实现,可以自动完成本地C或C数据类型与XML数据结构之间的转换。

该库提供了SOAP消息的生成,HTTP协议通信的实现,以及最终SOAP消息的生成和传输的相关支持设施。

本文使用的库文件主要是以下几个:

Stdsoap2.h和STD soap 2 . CPP:HTTP协议的实现和最终的SOAP消息生成。如果是C语言,stdsoap2.h和stdsoap2。使用了c。

Typemap.dat: wsdl2h工具在从wsdl文件生成头文件时需要这个文件,并且您可以更改项目的xml名称空间(稍后详细介绍)

Threads.h:实现高性能多线程服务器所需的文件可以并发处理请求,并且不会在服务操作变得耗时时阻塞其他客户端请求。

准备工作

先去官网下载页面,然后选择开源版本:

也可以直接点击开源版本的官方下载链接或者https://pan.baidu.com/s/156PEw9OMbzQel39Oozknow提取代码:gy4x。

将下载的压缩包解压(本文使用的是gsoap_2.8.117.zip),将解压后的文件放在自己习惯的位置(建议放在c盘)。

在命令提示符窗口中,使用cd命令输入..\gsoap_2.8.117\gsoap-2.8\gsoap\bin\win64目录:

注意:后面需要把头文件和typemap.dat放在程序目录下,生成的文件也在这里。

头文件

要使用gSOAP的编译工具生成代码,需要一个定义API的头文件。在这里,官方示例中的头文件calc.h用于两个数的加、减、乘、除或乘:

头文件calc.h可以由wsdl2h工具自动生成(需要Web服务的wsdl文件),cmd命令如下:

wsdl2h-o calc . h http://www.genivia.com/calc.wsdl

您也可以手动定义包含以下内容的calc.h头文件:

//gsoap ns服务方法将两个值相加

int ns__add(双a,双b,双结果);

//gsoap ns服务方法sub减去两个值

int ns__sub(双a,双b,双结果);

//gsoap ns服务方法mul将两个值相乘

int ns__mul(双a,双b,双结果);

//gsoap ns服务方法div划分两个值

int ns__div(双a,双b,双结果);

//gsoap ns服务方法pow将a提升到b

int ns__pow(双a,双b,双结果);

构建客户端应用程序

客户端应用程序在命令行上运行,并使用命令行参数调用calculator Web服务来对两个数字进行加、减、乘、除或乘。

生成soap源码

为客户端生成服务和数据绑定接口:

soapcpp2 -j -r -CL calc.h

其中选项-j生成C代理类,选项-r生成报告,选项-CL仅生成客户端,而没有(未使用的)lib文件。

这会生成以下几个文件:

其中,xml文件是肥皂报文的示例,便于后期的调试,以增加方法为例。

增加方法的请求报文ns.add.req.xml内容如下:

?可扩展标记语言版本='1.0 '编码='UTF八号'?

SOAP-ENV:Envelope

xmlns:SOAP-ENV=' http://模式。XML SOAP。org/SOAP/envelope/'

xmlns:SOAP-ENC=' http://模式。XML SOAP。org/SOAP/encoding/'

xmlns:xsi=' http://。w3。' org/2001/XML架构-实例'

xmlns:xsd=' http://。w3。' org/2001/XML架构'

xmlns:ns=' http://tempuri。组织/国家。xsd '

SOAP-ENV:Body

ns:添加

a0.0/a

b0.0/b

/ns:添加

/SOAP-ENV:Body

/SOAP-ENV:Envelope

增加方法的响应报文ns.add.req.xml内容如下:

?可扩展标记语言版本='1.0 '编码='UTF八号'?

SOAP-ENV:Envelope

xmlns:SOAP-ENV=' http://模式。XML SOAP。org/SOAP/envelope/'

xmlns:SOAP-ENC=' http://模式。XML SOAP。org/SOAP/encoding/'

xmlns:xsi=' http://。w3。' org/2001/XML架构-实例'

xmlns:xsd=' http://。w3。' org/2001/XML架构'

xmlns:ns=' http://tempuri。组织/国家。xsd '

SOAP-ENV:Body

ns:addResponse

结果0.0/结果

/ns:addResponse

/SOAP-ENV:Body

/SOAP-ENV:Envelope

建立客户端项目

建立一个C的控制台应用项目,引入上面生成的几个文件:

soapStub.h:没有注释的纯C/C头文件语法的规范副本。

soapH.h:声明可扩展标记语言序列化程序。

soapC.cpp:实现可扩展标记语言序列化程序。

soapProxy.h:定义客户端可扩展标记语言服务应用程序接口类代理人。

soapProxy.cpp:实现客户端可扩展标记语言服务应用程序接口类代理人。

calc.nsmap: XML命名空间绑定表到#包括。

还需要引入gSOAP解压目录下的stdsoap2.h和stdsoap2.cpp文件。

为方便调试,客户端程序示例改为固定参数调用增加方法,代码如下:

#include 'soapProxy.h '

#包含" ns.nsmap "

/* Web服务端点URL */

const char server[]=' http://localhost:8080 ';

int main(int argc,char** argv)

{

/*if (argc 4)

{

fprintf(stderr,用法:[add | sub | mul | div | pow]num num \ n ');

出口(1);

}*/

代理计算(服务器);

双甲,乙,结果;

/*a=strtod(argv[2],NULL);

b=strtod(argv[3],NULL);*/

a=3;

b=23

/*开关(*argv[1])*/

开关(“甲”)

{

案例“答”:

calc.add(a,b,result);

打破;

案例:

calc sub(a,b,result);

打破;

案例“m”:

calc.mul(a,b,result);

打破;

案例“d”:

calc.div(a,b,result);

打破;

案例“p”:

calc.pow(a,b,result);

打破;

默认值:

fprintf(stderr,未知命令\ n’);

出口(1);

}

如果(计算。肥皂-错误)

计算。soap _ stream _ fault(STD:cerr);

其他

STD:cout ' result=' result STD:endl;

计算。destroy();/*清理*/

STD:cout STD:endl;

返回0;

}

构建服务端应用程序

实现一个独立的迭代服务器,它接受主机端口上的传入请求,支持多线程,可以并发处理请求,并且在服务操作变得耗时时不会阻塞其他客户端请求。

生成SOAP源码

为服务器端生成服务和数据绑定接口:

soapcpp2 -j -r -SL calc.h

其中选项-j生成C服务类,选项-r生成报告,选项-SL仅生成服务器端,而没有(未使用的)lib文件。

生成的文件和客户端的文件名称一样,只是内容不同。

建立服务端项目

建立一个C的控制台应用项目,引入的生成文件和客户端的相同。为了支持多线程,需要引入文件线程。

服务端代码如下:

#包含" soapService.h "

#包含" ns.nsmap "

#include 'threads.h '

int port=8080

无效*流程_请求

{

Service * Service=(Service *)arg;

THREAD _ DETACH(THREAD _ ID);

如果(服务)

{

service-serve();

service-destroy();/*清理*/

删除服务;

}

返回空

}

int main()

{

服务服务(SOAP _ IO _ KEEPALIVE);/*启用HTTP kee-alive */

服务。soap-send _ time out=service。soap-recv _ time out=5;/* 5秒套接字空闲超时*/

服务。soap-transfer _ time out=30;/* 30秒消息传输超时*/

SOAP_SOCKET m=service.bind(NULL,port,100);/*主插座*/

if (soap_valid_socket(m))

{

while(soap _ valid _ socket(service。接受()))

{

线程类型tid

void * arg=(void *)服务。copy();

/*使用更新的THREAD _从插件/线程创建。https://www.genivia.com/files/threads.zip */

如果(参数)

while (THREAD_CREATE(tid,(void *)(void *))process _ request,arg))

睡眠(1);

}

}

服务。soap _ stream _ fault(STD:cerr);

服务。destroy();/*清理*/

返回0;

}

/*服务操作功能*/

int Service:add(双一,双b,双结果)

{

结果=a b;

返回SOAP _ OK

}

/*服务操作功能*/

int Service:sub(双一,双b,双结果)

{

结果=a-b;

返回SOAP _ OK

}

/*服务操作功能*/

int Service:mul(双一,双b,双结果)

{

结果=a * b;

返回SOAP _ OK

}

/*服务操作功能*/

int Service:div(双一,双b,双结果)

{

如果(二)

结果=a/b;

其他

返回soap_senderfault('除以零,NULL);

返回SOAP _ OK

}

/*服务操作功能*/

内部服务:pow(双一,双b,双结果)

{

result=:pow(a,b);

if(soap _ errno==EDOM)/* soap _ errno像错误,但是可移植*/

返回soap_senderfault('幂函数域错误,NULL);

返回SOAP _ OK

}

打印报文

在实际调试中,需要确定肥皂协议过程中具体的报文,只需要改动stdsoap2.cpp源码即可。参考gsoap报文打印,实现保存最后一次报文到特定的文件。

在stdsoap2.h头文件包括下添加fstream,内容如下:

#include 'stdsoap2.h '

#包括fstream

soap_begin_recv函数开始处添加以下代码:

//发送完请求报文获取请求报文信息(作为客户端的时候)

STD:string str _ req XML=“”;

STD:string strBuf;

STD:string:size _ type pos 1=STD:string:NPOs;

STD:string:size _ type pos 2=STD:string:NPOs;

strBuf=soap-buf;

pos1=strBuf.find('?xml ',0);

位置2=strbuf。find('/SOAP-ENV:Envelope ',0);

if (pos1!=std:string:npos pos2!=std:string:npos)

{

str_reqXml=strBuf.substr(pos1,pos 2-pos 1 20);

}

STD:of stream outfile;

文件输出。打开('请求XML。txt’);

outfile str _ reqXml

文件输出。close();

soap_body_end_in函数开始处添加以下代码:

//接收完应答报文获取应答报文信息(作为客户端的时候)

STD:string str _ resXml=" ";

STD:string strBuf;

STD:string strEnd='/SOAP-ENV:Envelope ';

STD:string:size _ type pos 1=STD:string:NPOs;

STD:string:size _ type pos 2=STD:string:NPOs;

pos 1=STD:string:NPOs;

pos 2=STD:string:NPOs;

SOAP-buf[SOAP _ buf len-1]=' \ 0 ';

strBuf=soap-buf;

pos1=strBuf.find('?xml ',0);

pos2=strBuf.find(strEnd,0);

if (pos1!=std:string:npos pos2!=std:string:npos)

{

str_resXml=strBuf.substr(pos1,pos 2-pos 1 strend。length());

}

STD:of stream outfile;

文件输出。打开(' resxml。txt’);

outfile str _ resXml

文件输出。close();

肥皂_接收_原始函数结尾处(返回前)添加以下代码:

//请求报文(作为服务端的时候)

STD:string req _ data;

req_data.assign(soap-buf,ret);

STD:of stream outfile;

文件输出。打开(' req _ data。txt’);

outfile req _ data

文件输出。close();

肥皂_冲洗_原始函数结尾处(返回前)添加以下代码:

//应答报文(作为服务端的时候)

STD:string RES _ data;

res_data.assign(s,n);

STD:of stream outfile;

文件输出。打开(' RES _ data。txt’);

outfile res _ data

文件输出。close();

注:客户端可以一直打印报文,服务端只能在调试运行时才会打印报文,应该有其它方法可以解决。

SOAP测试

运行上面的服务器和客户端项目,可以看到运行API调用的结果,也可以使用SoapUI进行测试。

去官方网站的下载链接:https://www.soapui.org/downloads/soapui/,下载开源版本并安装。

打开软件,在菜单栏的“文件”中选择“新建SOAP项目”:

展开左边的项目,双击“请求”开始测试:

项目源码

SoapTest提取代码:89mu

总结

本文到此为止。希望能帮到你,也希望你能多关注我们的更多内容!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

相关文章阅读

  • vs2015打包安装程序,vs2015程序打包,VS2022实现VC++打包生成安装文件图文详细历程
  • vc++6.0的快捷键,vc 快捷键
  • vc++6.0的快捷键,vc 快捷键,VC6.0常用快捷键大全
  • 绘制圆角矩形的方法,c++ 画矩形,C#画圆角矩形的方法
  • 懒汉式和饿汉式代码,单列模式懒汉和饿汉,C++单例模式的懒汉模式和饿汉模式详解
  • 好用的C++编译器,c++编译软件哪个好
  • semaphore c#,c++ semaphore
  • semaphore c#,c++ semaphore,C++中Semaphore内核对象用法实例
  • dev-c++使用教程,dev c++安装教程
  • dev-c++使用教程,dev c++安装教程,Dev C++ 安装及使用方法(图文教程)
  • C里面指针常量和常量指针的区别,c++指针常量和常量指针
  • C里面指针常量和常量指针的区别,c++指针常量和常量指针,简单总结C++中指针常量与常量指针的区别
  • com组件初始化失败,c#开发com组件,C++中COM组件初始化方法实例分析
  • c++静态成员变量使用,c++静态成员函数和静态成员变量
  • c++静态成员变量使用,c++静态成员函数和静态成员变量,详解c++ 静态成员变量
  • 留言与评论(共有 条评论)
       
    验证码: