gSOAP 学习


由于工作调动关系,需要了解 gSOAP 的使用,写个文章记录一下学习的心得,免得以后忘记。

安装

由于本人使用的是 Mac OS 系统,故以 Mac OS 为例说明如何安装 gSOAP。

1)下载 gSOAP

可以在 https://sourceforge.net/projects/gsoap2 下载最新版本的 gSOAP。

2)安装 flex, bison, openssl

可以使用brew install进行安装:

brew install flex bison openssl
 
 
  • 1

3)编译安装 gSOAP

解压上面下载的 gSOAP,然后执行下面的命令:

cd gsoap-2.8
./configure --with-openssl=/usr/local/opt/openssl
make
sudo make install
 
 
  • 1
  • 2
  • 3
  • 4

安装完成,会出现以下的提示:

安装中如果出现 fatal error: 'openssl/bio.h' file not found 的错误,可以通过尝试重新安装 openssl 和使用最新的 gsoap-2.8 版本的方法来解决,具体解决办法也可以 google 一下。

其他平台的安装教程可以参考官方文档:https://www.genivia.com/downloads.html

gSOAP 工具

gSOAP 提供了两个工具来方便开发人员使用 C/C++ 语言快速开发Web 服务应用,通过 gSOAP 提供的这两个工具,开发人员可以快速生成服务端与客户端代码框架,接下来开发人员只需要实现具体的接口函数即可。

wsdl2h

wsdl2h 工具根据 WSDL 文件生成 C/C++ .h 头文件。
WSDL(Web Service Description Language)即 Web 服务描述语言,它使用 XML 来对 Web 服务进行描述。
wsdl2h 的用法:

wsdl2h -o 头文件名 WSDL文件名或URL
 
 
  • 1

例如:

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

wsdl2h 根据 URL 指定的 WSDL 生成calc.h头文件。calc.h对 Web 服务接口进行定义。

wsdl2h 支持额外的参数:

  • -s 生成的头文件不使用 STL
  • -o 文件名,指定输出头文件的名称
  • -c 产生纯 C 代码,否则是 C++ 代码
  • -t 文件名,指定 type map 文件,默认是 typemap.dat

soapcpp2

soapcpp2 工具则从上面生成的头文件生成 SOAP 服务端和客户端框架代码。例如对于上面的cacl.h,使用 soapcpp2 命令:

soapcpp2 -i -Iimport calc.h
 
 
  • 1

soapcpp2 也支持额外的参数:

  • -i 生成 C++ 包装类,客户端为 xxxProxy.h(.cpp),服务端为xxxService.h(.cpp)
  • -I 指定 import 的路径,比如需要引入stlvector.h文件来支持 STL vector 的序列化
  • -C 仅生成客户端代码
  • -S 仅生成服务端代码
  • -c 产生纯 C 代码,否则是 C++ 代码
  • -x 不要产生 XML 示例文件
  • -L 不要产生soapClientLib.csoapServerLib.c文件

例子

gSOAP 中包含了大量的例子以便让开发人员快速了解如何使用 gSOAP 开发 Web 服务。
我们以 gSOAP 的 samples 目录下的 calc++ 的代码为例,说明如何使用 gSOAP 来编写客户端和的服务端代码。

calc++ 目录已经包含了 calc.h 头文件,这个头文件跟上面我们使用 wsdl2h 生成的 calc.h 头文件并不完全相同,为了实验的方便,我们使用 calc++ 目录的calc.h 头文件进行实验。

calc.h头文件:

//gsoap ns service method: add Sums two values
int ns__add(double a, double b, double *result);

//gsoap ns service method: sub Subtracts two values
int ns__sub(double a, double b, double *result);

//gsoap ns service method: mul Multiplies two values
int ns__mul(double a, double b, double *result);

//gsoap ns service method: div Divides two values
int ns__div(double a, double b, double *result);

//gsoap ns service method: pow Raises a to b
int ns__pow(double a, double b, double *result);
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

然后,我们使用 soapcpp2 工具来生成客户端和服务端的框架代码:

soapcpp2 -i -Iimport calc.h
 
 
  • 1

客户端代码

calcclient.c++ 代码:

#include "soapcalcProxy.h"
#include "calc.nsmap"

const char server[] = "http://127.0.0.1:8080";

int main(int argc, char **argv)
{ if (argc < 4)
  { fprintf(stderr, "Usage: [add|sub|mul|div|pow] num num\n");
    exit(0);
  }
  double a, b, result;
  a = strtod(argv[2], NULL);
  b = strtod(argv[3], NULL);
  calcProxy calc;
  calc.soap_endpoint = server;
  switch (*argv[1])
  { case 'a':
      calc.add(a, b, &result);
      break;
    case 's':
      calc.sub(a, b, &result);
      break;
    case 'm':
      calc.mul(a, b, &result);
      break;
    case 'd':
      calc.div(a, b, &result);
      break;
    case 'p':
      calc.pow(a, b, &result);
      break;
    default:
      fprintf(stderr, "Unknown command\n");
      exit(0);
  }
  if (calc.error)
    calc.soap_stream_fault(std::cerr);
  else
    printf("result = %g\n", result);
  return 0;
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

由于代码使用 STL,为了顺利编译通过,需要将 gSOAP 中的stdsoap2.cppstdsoap2.h文件拷贝到客户端和服务端代码所在的目录。
改写好客户端代码后,使用 g++ 进行编译:

g++ -o calcclient calcclient.cpp soapC.cpp soapcalcProxy.cpp stdsoap2.cpp
 
 
  • 1

编译顺利通过。

服务端代码

calcserver.cpp代码如下,其中可以指定服务端的端口号:

#include "soapcalcService.h"
#include "calc.nsmap"

int main(int argc, char **argv)
{ calcService calc;
  if (argc < 2)
    calc.serve();   /* serve as CGI application */
  else
  { int port = atoi(argv[1]);
    if (!port)
    { fprintf(stderr, "Usage: calcserver++ <port>\n");
      exit(0);
    }
    /* run iterative server on port until fatal error */
    if (calc.run(port))
    { calc.soap_stream_fault(std::cerr);
      exit(-1);
    }
  }
  return 0;
} 

int calcService::add(double a, double b, double *result)
{ *result = a + b;
  return SOAP_OK;
} 

int calcService::sub(double a, double b, double *result)
{ *result = a - b;
  return SOAP_OK;
} 

int calcService::mul(double a, double b, double *result)
{ *result = a * b;
  return SOAP_OK;
} 

int calcService::div(double a, double b, double *result)
{ if (b)
    *result = a / b;
  else
  { char *s = (char*)soap_malloc(this, 1024);
    (SOAP_SNPRINTF(s, 1024, 100), "<error xmlns=\"http://tempuri.org/\">Can't divide %f by %f</error>", a, b);
    return soap_senderfault("Division by zero", s);
  }
  return SOAP_OK;
} 

int calcService::pow(double a, double b, double *result)
{ *result = ::pow(a, b);
  if (soap_errno == EDOM)   /* soap_errno is like errno, but compatible with Win32 */
  { char *s = (char*)soap_malloc(this, 1024);
    (SOAP_SNPRINTF(s, 1024, 100), "<error xmlns=\"http://tempuri.org/\">Can't take power of %f to %f</error>", a, b);
    return soap_senderfault("Power function domain error", s);
  }
  return SOAP_OK;
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57

然后使用 g++ 来对服务端代码进行编译:

g++ -o calcserver calcserver.cpp soapC.cpp soapcalcService.cpp stdsoap2.cpp
 
 
  • 1

编译同样顺利通过。

测试

运行上面编译好的calcservercalcclient可执行文件
来对 Web 服务进行测试,测试结果如下:

参考资料


  1. https://www.cs.fsu.edu/~engelen/soapdoc2.html
  2. https://www.genivia.com/downloads.html
  3. https://www.genivia.com/dev.html
  4. http://blog.csdn.net/yangjun1115/article/details/29360389
  5. https://www.cs.fsu.edu/~engelen/calc.html
  6. http://commandos.blog.51cto.com/154976/130652
  7. http://www.cppblog.com/qiujian5628/archive/2008/10/11/54019.html
  8. http://blog.sina.com.cn/s/blog_5ee9235c0100de3g.html

gSOAP编译工具提供了一个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的一些特点:   ×gSOAP编译器可以根据用户定义的C和C++数据结构自动生成符合SOAP的实例化代码。   ×gSOAP支持WSDL 1.1, SOAP 1.1, SOAP 1.2, SOAP RPC 编码方式以及 literal/document 方式.   ×gSOAP是少数完全支持SOAP1.1 RPC编码功能的工具包,包括多维数组及动态类型。比如,一个包含一个基类参数的远程方法可以接收客户端   传来的子类实例。子类实例通过动态绑定技术来保持一致性。   ×gSOAP 支持 MIME (SwA) 和 DIME 附件包。   ×gSOAP是唯一支持DIME附件传输的工具包。它允许你在保证XML可用性的同时能够以最快的方式(流方式)传递近乎无大小限制的二进制数据   。   ×gSOAP 支持 SOAP-over-UDP。   ×gSOAP 支持 IPv4 and IPv6.   ×gSOAP 支持 Zlib deflate and gzip compression(for HTTP, TCP/IP, and XML file storage)。   ×gSOAP 支持 SSL (HTTPS)。   ×gSOAP 支持 HTTP/1.0, HTTP/1.1 保持连接, 分块传输及基本验证。   ×gSOAP 支持 SOAP 单向消息。   ×gSOAP 包含一个 WSDL 生成器,便于web服务的发布。   ×gSOAP 包含一个WSDL解析器(将WSDL转换为gSOAP头文件),可以自动化用户客户端及服务端的开发。   ×生成可以单独运行的web服务及客户端程序。   ×因为只需要很少内存空间,所以可以运行在类似Palm OS, Symbian, Pocket PC的小型设备中。   ×适用于以C或C++开发的web服务中。   ×跨平台:Windows, Unix, Linux, Mac OS X, Pocket PC, Palm OS, Symbian等。   ×支持序列化程序中的本地化C/C++数据结构。   ×可以使用输入和输出缓冲区来提高效率,但是不用完全消息缓冲来确定HTTP消息的长度。取而代之的是一个三相序列化方法。这样,像64位   编码的图像就可以在小内存设备(如PDA)中以DIME附件或其他方式传输。   ×支持C++单继承,动态绑定,重载,指针结构(列表、树、图、循环图,定长数组,动态数组,枚举,64位2进制编码及16进制编码)。   ×不需要重写现有的C/C++应用。但是,不能用unions,指针和空指针来作为远程方法调用参数的数据结构中元素。   ×三相编组:1)分析指针,引用,循环数据结构;2)确定HTTP消息长度;3)将数据序列化位SOAP1.1编码方式或用户定义的数据编码方式。   ×双相编组:1)SOAP解释及编码;2)分解“forward”指针(例如:分解SOAP中的href属性)。   ×完整可定制的SOAP错误处理机制。   ×可定制的SOAP消息头处理机制,可以用来保持状态信息   2 gSoap2.2版与gSOAP 2.1版(或以前版本)的不同   如果你是从2.1版升级到2.2或以后版本,请注意这些变化。   为了能够分离传输、内容编码、映射中的接收/发送设置,改变了运行时选项及标志。这些标志分布再四个类中:传输(IO),内容编码(ENC   
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值