gSoap使用总结

本文详细介绍了如何使用gSoap开发包进行客户端程序的开发,包括如何使用wsdl2h.exe和soapcpp2.exe工具从wsdl文件生成接口头文件,并通过实例展示了如何创建计算器服务的客户端程序。在开发过程中,强调了接口定义、命名空间一致性以及编译时的警告信息处理的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

向导 1.1节中提供了gSoap开发包的下载地址http://sourceforge.net/projects/gsoap2

下载最新gSoap程序包
解压后在\gsoap\bin\win32(windowsXP下,其它操作系统就自己选择)下找到 编译器soapcpp2.exe 和wsdl解析工具 wsdl2h.exe,这两个文件也可以重新编译生成,用户向导中有介绍,此处就不多说,用现成的了。

 

进入主题:开发客户端程序
    (1)客户端服务端通信必不可少的一个东西:接口定义。
          gSoap使用中,需要此接口文件(也就是以后常提到的头文件)此文件可以两种方式得到:
          1: 由现有的wsdl文件转换得到(本文使用这种方式)
          2: 自己编写

    (2)两个工具的用途
          wsdl2h.exe--------名字就能看出来,完成 wsdl文件(.wsdl)到(2)头文件(.h)的转换,即由写好的wsdl格式的接口定义文件转换为C/C++格式的头文件         

          soapcpp2.exe------根据接口头文件生成应用程序客户端和服务端的框架文件(soapClient.cpp、soapServer.cpp等).

 

结合例子说明过程
示例:引用向导中的例子--计算器
      由wsdl文件生成接口头文件
      wsdl文件URL地址:http://www.cs.fsu.edu/~engelen/calc.wsdl
      操作流程
      a) 程序->运行 输入cmd 启动命令行;
      b) 打开wsdl2h.exe所在文件路径(不打开的话下面输入时要记着输入全路径,不然找不着了);
      c) 输入:wsdl2h.exe -o cal.h http://www.cs.fsu.edu/~engelen/calc.wsdl,
         其中
             "wsdl2h.exe",因为第二步中打了wsdl2h文件所在路径,所以此处可以直接用了,若没打开要输入所在完整路径
             "cal.h"为生成的头文件名,此文件的保存位置在wsdl2h.exe同一文件目录下(要修改的话要请参照命令行语法规则,此处不多说了,有点脱离主题)            

       "-o"是生成选项,表示输出,也可以增加其它选项(向导中出现 "-s -o"、"-c -o"等),具体选项说明请参照向导中介绍。
             "http://www.cs.fsu.edu/~engelen/calc.wsdl"是wsdl文件的位置,此处是在网络地址(这个地址是可以用的),如果wsdl文件在本地的也可以,路径设置好就OK了
         注意:以上四项中每项间都有空格分开 不要手误啊!
      d) 回车 运行吧,看提示信息,没有提示故障的话,查找cal.h吧(cal.h的保存路径要记好啊,自己设置的);
      e) 得到cal.h后,打开可以看到接口定义;
      f) 在命令行中 输入:soapcpp2.exe cal.h
         其中
             "soapcpp2.exe",此处把soapcpp2.exe和wsdl2h.exe放在同一目录下了,且前面已打开此路径;
             "cal.h"即由wsdl生成的头文件,此文件保存位置与soapcpp2.exe相同,故此处可这样输入,若不同还须设置文件路径;
             同样两项之间也有空格!
             可以增加控制选项如"soapcpp2.exe -C cal.h"则只生成客户端所需文件, "soapcpp2.exe -S calc.h"则只生成服务端所需文件
      g) 回车 运行。
  如果提示找不到文件 stlvector.h,因为cal.h文件中引用了文件stlvector.h;解决方法:开发包\gsoap\import目下有此文件,复制一份到cal.h所在目录。
         注意:此过程中要检查生成的编译信息,确保没有警告信息出现(警告信息可能是gSoap不支持的内容,如果不去除,程序运行故障很难找到根本原因),另不能只看编译结果成功就认为是正确的,存在警告信息也显示为编译成功!!
      h) 编译成功,生成的框架文件保存位置与cal.h在同一目录下,包括:calc.nsmap、soapC.cpp、soapcalcObject.h、soapcalcProxy.h、soapClient.cpp、soapClient.lib

、soapH.h、soapServer.cpp、soapServer.Lib、soapStub.h和接口的请求应答xml文件。
    其中
      calc.nsmap 为命名空间定义文件;
      soapClient.cpp 客户端文件
            soapServer.cpp 服务端文件
            soapcalcProxy.h 代理用到
            soapStub.h 此文件中为程序中要用到的接口的声明(将cal.h中的接口经过处理后,在程序中供调用的接口)
            xml文件 为接口的xml格式,可以据此帮助调试等。。。
            其它文件作用还没完全搞明白,向导中有说明,此处不说了以免误导^_^
      i) 编译过程完成。下面开始程序(客户端)
         VC6中新建空的win32控制台工程,新建源文件calcClient.cpp;
         复制编译生成的文件(包括cal.h和stlvector)到程序目录中;
         在工程中添加文件calc.nsmap、soapC.cpp、soapClient.cpp、soapH.h、soapStub.h(使用代理添加soapcalcProxy.h);
         编译,提示无法找到文件stdsoap2.h、stdsoap2.cpp文件,这两个文件为gSoap的源码文件,在\gsoap文件夹中找到这两个文件,复制到程序目录下并添加到工程中;
         在calcClient.cpp文件中 添加语句#include "soapH.h", #include "calc.nsmap"

///calcClient.cpp源码//
#include <stdio.h>
#include "soapH.h"
#include "calc.nsmap"

const char server[] = "http://websrv.cs.fsu.edu/~engelen/calcserver.cgi";

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_init(&soap);
 a = strtod(argv[2], NULL);
 b = strtod(argv[3], NULL);
 switch (*argv[1])
 { case 'a':
   soap_call_ns2__add(&soap, server, "", a, b, result);
   break;
 case 's':
   soap_call_ns2__sub(&soap, server, "", a, b, result);
   break;
 case 'm':
   soap_call_ns2__mul(&soap, server, "", a, b, result);
   break;
 case 'd':
   soap_call_ns2__div(&soap, server, "", a, b, result);
   break;
 case 'p':
   soap_call_ns2__pow(&soap, server, "", a, b, result);
   break;
 default:
   fprintf(stderr, "Unknown command\n");
   exit(0);
 }
 if (soap.error)
 { soap_print_fault(&soap, stderr);
 exit(1);
 }
 else
 printf("result = %g\n", result);
 soap_destroy(&soap);
 soap_end(&soap);
 soap_done(&soap);
 return 0;
}
//calcClient.cpp源码 
其中soap_call_ns2__add、soap_call_ns2__sub、soap_call_ns2__mul、soap_call_ns2__div、soap_call_ns2__pow为接口函数,在soapStub.h中可以找到函数声明。
^_^搞定一步^_^
calcClient.cpp内容引用了gSoap开发包中例程中calc的源码,函数名略有修改动!代码中没有做接口执行故障检测,仅供参考。
这个例子中还有很多东西没写明白,比如gSoap中接口函数的定义的原则、gSoap的初始化和结束清理等。


接口头文件的格式在向导中没有看到明确的说明性的内容,但通过看开发包中示例程序中头文件定义和通过wsdl生成的头文件的内容,可以发现,头文件中都会出现以下几行信息
 //gsoap ns service name: calc Simple calculator service
 //gsoap ns service style: rpc
 //gsoap ns service encoding: encoded
 //gsoap ns service namespace: http://websrv.cs.fsu.edu/~engelen/calc.wsdl
 //gsoap ns service location: http://websrv.cs.fsu.edu/~engelen/calcserver.cgi

 //gsoap ns  service method-style: add rpc
 //gsoap ns  service method-encoding: add http://schemas.xmlsoap.org/soap/encoding/
 //gsoap ns  service method-action: add ""
这些都是头文件中的说明性信息,编译时会用到这里的信息,这些信息有命名空间的和服务名称的名字,有些信息为默认参数信息,如service location 如果在客户端调用接口方法时,没有输入服务端地址,方法执行时将自动调用此处的地址做为服务器地址。后三行是对add方法的说明,在写头文件时可以修改一下这些说明信息如下:
 //gsoap ns service name: calc Simple calculator service
 //gsoap ns service style: rpc
 //gsoap ns service namespace: urn:calc
 //gsoap ns service location: http://websrv.cs.fsu.edu/~engelen/calcserver.cgi
这些信息是很重要的,如果是已定义好的接口,一定要注意命名空间名字统一。

下面开始主要工作:接口定义
        gSoap对“_”和“__”(下划线、双下划线)有特殊用法,接口定义时函数名前要加上命名空间名和双下划线
        举例:加法运算
        int add(int num1, int num2, int &num3);
        在接口头文件定义时要写成如下格式
        int ns__add(int num1, int nmu2, int &num3);
        其中
        "ns"是命名空间名称,此名称可以自定义成其它名字 但其后"urn:calc"不可随意更改,这个是要与服务端统一的
        "__"是编译时识别符号,如果没有的话xml文件是编译不出来的
       
 "_"(单下划线)定义名称中要慎用,自己定义的变量或函数名称中使用下划线的地方要在下划线后加上"USCORE"
        例 定义 ns__add_sum(int num_1, int num2, int &num_3);
        要写成如下形式
                ns__add_USCOREsum(int num_USCORE1, int num2, int &num_USCORE3);

 "add"是接口函数名 这个是客户端与服务器统一的接口名字
        函数内参数变量类型和变量名 为客户端与服务器统一的接口
        函数中只有最后一个参数是输出参数,前面的都是输入参数若有多个输出信息,可定义结构体
        若没有输入参数 可将输入参数类型定义为void *(将忽略void *类型的参数),一般参数只写类型不写参数变量。

 函数返回类型必须为 int,可以通过返回值判断接口函数执行情况至此接口定义要注意的地方完毕,开始写接口定义文件。

本例中使用自定义的头文件,编写客户端程序,但服务器仍与上篇中服务器相同,以便说明两种方式的结果,接口可以从上篇中由wsdl生成的头文件中获得。
源码如下:
///mycalc.h///
//gsoap ns service name: mycalc
//gsoap ns service style: rpc
//gsoap ns service namespace: urn:calc
//gsoap ns service location: http://websrv.cs.fsu.edu/~engelen/calcserver.cgi

int ns__add(double a, double b, double &result);

int ns__sub(double a, double b, double &result);

int ns__mul(double a, double b, double &result);

int ns__div(double a, double b, double &result);

int ns__pow(double a, double b, double &result);
///mycalc.h///
上面文件中一定要注意 //gsoap ns service namespace: urn:calc 由于服务器中接口命名空间为calc 故此处必须是calc!
开始编译此头文件
运行 soapcpp2.exe mycalc.h
编译成功,写客户端程序
新建工程mycalcClient, 添加生成的文件,新建源文件mycalcClient.cpp
源码如下
//mycalcClient.cpp/
#include <stdio.h>
#include "soapH.h"
#include "calc.nsmap"

const char server[] = "http://websrv.cs.fsu.edu/~engelen/calcserver.cgi";

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_init(&soap);
 a = strtod(argv[2], NULL);
 b = strtod(argv[3], NULL);
 switch (*argv[1])
 { case 'a':
   soap_call_ns__add(&soap, server, "", 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)
 { soap_print_fault(&soap, stderr);
 exit(1);
 }
 else
 printf("result = %g\n", result);
 soap_destroy(&soap);
 soap_end(&soap);
 soap_done(&soap);
 return 0;
}
//mycalcClient.cpp/
测试一下吧^_^

对比两种生成接口头文件的方法,选择那一种还要视情况而定
如果是已有写好的wsdl文档,当然是选择用wsdl2h工具来生成头文件了,毕竟这个方便的多,但在编译时,一定要检查警告信息,有些情况下生成的接口头件存在编译异常,例如复杂数据结构时就有可能出现结构体命名不符合gSoap命名规则(实际应用中遇至过,此时要手动修改这些命名)

简单说一下soap结构体初始化及清理
 soap_init(&soap);//初始化
 …………
 soap_destroy(&soap);//结束清理操作
 soap_end(&soap);
 soap_done(&soap);
向导中这方面讲的比较细^_^

两篇都只是写了客户端的程序,因为是一直在与现成的服务器端通信,在此就没列出自己的服务器程序;
利用gSoap开发服务器端程序也比较方便的,开发包例程中都附有源程序,自己参考吧^_^


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值