gsoap使用笔记

gsoap入门

1 使用gsoap搭建web service

参考了参考文档[2]中的介绍,有一点点修改。

1.1 编译calc客户端

  1. 根据wsdl文件生成gsoap用的头文件
wsdl2h -o calc.h http://www.genivia.com/calc.wsdl
  1. 如果用我们自己搭建的webserver,需要修改头文件中的如下代码,
    把port字段修改为自己的webservice的url。
//gsoap ns2  service port:      http://websrv.cs.fsu.edu/~engelen/calcserver.cgi

改为

//gsoap ns2  service port:      http://localhost:9999/cgi-bin/calcserver.cgi
  1. 生成client proxy类的源代码
soapcpp2 -j -CL -I/usr/share/gsoap/import calc.h

-j生成C++ proxy类,供client调用,-CL生成客户端程序,-I指明gsoap相关头文件路径,这个根据gsoap安装位置而定,例子中的路径是ubuntu通过apt-get安装的gsoap的路径。

  1. 编写client程序calcclient.cpp
#include "calc.nsmap"      // XML namespace mapping table (only needed once at the global level)
#include "soapcalcProxy.h" // the proxy class, also #includes "soapH.h" and "soapStub.h"
int main()
{
  calcProxy calc;
  double sum;
  if (calc.add(1.23, 4.56, sum) == SOAP_OK)
    std::cout << "Sum = " << sum << std::endl;
  else
    calc.soap_stream_fault(std::cerr);
  calc.destroy(); // same as: soap_destroy(calc.soap);
  soap_end(calc.soap);
}

调用proxy类calcProxyadd方法,传递了2个参数1.23 4.56,打印结果。

  1. 编译
c++ -o calcclient calcclient.cpp soapC.cpp soapcalcProxy.cpp -lgsoap++

如果第二步没修改port的话,这时候执行calcclient就能得到结果了,如果修改了port,我们需要自己搭建一个webservice来提供calc服务。

1.2 搭建服务器

1.2.1 编译服务器端程序

  1. 与client第一步一样,生成calc.h
wsdl2h -o calc.h http://www.genivia.com/calc.wsdl
  1. 生成server端的接口类
soapcpp2 -j -SL -I/usr/share/gsoap/import calc.h
  1. 编写cgi程序calcserver.cpp,实现calc服务器端的接口
#include "calc.nsmap"        // XML namespace mapping table (only needed once at the global level)
#include "soapcalcService.h" // the service class, also #includes "soapH.h" and "soapStub.h"
int main()
{
  calcService calc(SOAP_XML_INDENT);
  if (calc.serve() != SOAP_OK)
    calc.soap_stream_fault(std::cerr);
  calc.destroy(); // same as: soap_destroy(calc.soap);
  soap_end(calc.soap);
}
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 == 0.0)
  {
    char *msg = (char*)soap_malloc(this->soap, 1024);
    snprintf(msg, 1024, "Trying to divide %f by zero", a);
    return this->soap_senderfault(msg, NULL);
  }
  result = a / b;
  return SOAP_OK;
}
int calcService::pow(double a, double b, double &result)
{
  result = ::pow(a, b);
  // soap_errno is like errno, but compatible with Win32
  if (soap_errno == EDOM)
  {
    char *msg = (char*)soap_malloc(this->soap, 1024);
    snprintf(msg, 1024, "<error xmlns=\"http://tempuri.org/\">Can't take power of %f to %f</error>", a, b);
    return this->soap_senderfault("Power function domain error", msg);
  }
  return SOAP_OK;
}
  1. 编译,测试
c++ -o calcserver calcserver.cpp soapC.cpp soapcalcService.cpp -lgsoap++
./calcserver < calc.add.req.xml

这时候calcserver是一个cgi程序,从标准输入读取soap命令,输出到标准输出上。接下来搭建一个webserver来提供cgi服务。

1.2.2 搭建cgi服务器

简单起见,使用docker启动一个apache来作为web server。

  1. 下载apache镜像
docker pull httpd:2.4
  1. 修改http.conf文件,启动apache对cgi的支持。
    取得http.conf文件,修改其中的cgi支持,打开下面内容的注释即可
LoadModule cgi_module modules/mod_cgi.so
  • http.conf在docker container的路径为:/usr/local/apache2/conf/httpd.conf
  • 这步不做的话,运行client的时候,会提示如下错误,即apache把cgi请求当成了下载文件的请求。
Error 200 fault: SOAP-ENV:Client[no subcode]
"Error 200"
Detail: [no detail]
  1. 启动服务,在calcserverhttp.conf所在目录输入如下命令:
docker run -it --rm --name my-apache-app -p 9999:80 -v "$PWD":/usr/local/apache2/cgi-bin -v "$PWD"/http.conf:/usr/local/apache2/conf/httpd.conf -v /usr/lib/x86_64-linux-gnu/libgsoap++.so.4:/usr/lib/x86_64-linux-gnu/libgsoap++.so.4 httpd:2.4

1.3 其他

1.3.1 问题

gsoap也支持自己作为web服务器提供服务,只需要修改server代码,即可,但我没有试验成功。

int main()
{
  calcService calc(SOAP_XML_INDENT);
  //if (calc.serve() != SOAP_OK) <--这里改为调用run
  if (calc.run(9999) != SOAP_OK)
    calc.soap_stream_fault(std::cerr);
  calc.destroy(); // same as: soap_destroy(calc.soap);
  soap_end(calc.soap);
}

这时运行服务器程序时始终提示:

setsockopt unset IPV6_V6ONLY failed in soap_bind()

1.3.2 curl调试webservice服务器

可以使用curl模拟客户端请求一个soap服务[4],命令如下:

curl -v --header "content-type: application/soap+xml"  --data @calc.add.req.xml localhost:9999/cgi-bin/calcserver.cgi

2 编译arm-linux版本的gsoap

2.1 下载gsoap源码

http://liquidtelecom.dl.sourceforge.net/project/gsoap2/gSOAP/gsoap_2.8.33.zip

2.2 配置编译环境

  1. 下载linaro toolchain,解压到目录/usr/local/linaro-multilib-2014.06-gcc4.9
  2. 设置PATH环境变量。export PATH=/usr/local/linaro-multilib-2014.06-gcc4.9:$PATH

2.3 config&make

2.3.1 生成makefile

gsoap-2.8$ ./configure --host=arm-linux-gnueabihf --prefix=/usr/local/arm-linux
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for arm-linux-gnueabihf-strip... arm-linux-gnueabihf-strip
checking for a thread-safe mkdir -p... /bin/mkdir -p
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking whether make supports nested variables... yes
checking build system type... x86_64-unknown-linux-gnu
checking host system type... arm-unknown-linux-gnueabihf
checking whether make sets $(MAKE)... (cached) yes
checking for arm-linux-gnueabihf-g++... arm-linux-gnueabihf-g++
checking whether the C++ compiler works... yes
checking for C++ compiler default output file name... a.out
checking for suffix of executables... 
checking whether we are cross compiling... yes
...
  • --host=arm-linux-gnueabihf - 表明编译的库是运行在arm linux上,这个也是gcc编译器的前缀。
  • --prefix=/usr/local/arm-linux - 表明变编译好的库的安装路径

2.3.2 手动生成wsdl.h文件

gsoap-2.8$ cd gsoap/wsdl
gsoap-2.8/gsoap/wsdl$ ../../target-amd64/bin/soapcpp2 -SC -pwsdl -I. -I../../gsoap/import ./wsdl.h

**  The gSOAP code generator for C and C++, soapcpp2 release 2.8.33
**  Copyright (C) 2000-2016, Robert van Engelen, Genivia Inc.
**  All Rights Reserved. This product is provided "as is", without any warranty.
**  The soapcpp2 tool and its generated software are released under the GPL.
**  ----------------------------------------------------------------------------
**  A commercial use license is available from Genivia Inc., contact@genivia.com
**  ----------------------------------------------------------------------------

soapcpp2: using both options -C and -S omits client/server code
Saving wsdlStub.h annotated copy of the source interface file
Saving wsdlH.h serialization functions to #include in projects
Saving xmime.nsmap namespace mapping table
Saving wsdlC.cpp serialization functions

Compilation successful 

../../target-amd64/bin/soapcpp2这个是你的host机器可以运行的soapcpp2

如果不做这步,在编译过程中会提示如下错误,因为编译时,生成的soapcpp2是只能在arm linux上运行的。

make[4]: Entering directory `/home/meng/git/gsoap-2.8/gsoap/wsdl'
../../gsoap/src/soapcpp2 -SC -pwsdl -I. -I../../gsoap/import ./wsdl.h
/bin/bash: ../../gsoap/src/soapcpp2: cannot execute binary file: Exec format error
make[4]: *** [wsdlC.cpp] Error 126

2.3.3 修改代码

修改config.h文件,删除最后一行的#define malloc rpl_malloc
否则编译会出错
`

2.3.4 修改makefile

修改gsoap/wsdl目录下的Makefile,删除下面2行(因为wsdl2h对其他库有依赖,并且我们也不需要arm版本的wsdl2h程序):

wsdl2h$(EXEEXT): $(wsdl2h_OBJECTS) $(wsdl2h_DEPENDENCIES) $(EXTRA_wsdl2h_DEPENDENCIES) 
    #@rm -f wsdl2h$(EXEEXT)
    #$(AM_V_CXXLD)$(wsdl2h_LINK) $(wsdl2h_OBJECTS) $(wsdl2h_LDADD) $(LIBS)

2.3.5 编译,安装

gsoap-2.8$ make
gsoap-2.8$ make install

在目录/usr/local/arm-linux下是编译好的gsoap库,注:我们没有编译出来arm linux版本的wadl2h

2.4 编译arm-linux版calcserver.cgi

  • 编译cgi版本的calcserver.cgi
calcserver$ arm-linux-gnueabihf-g++ -o calcserver.cgi calcserver.cpp soapC.cpp soapcalcService.cpp -lgsoap++ -DWITH_FASTCGI -L/usr/local/arm-linux/lib -I/usr/local/arm-linux/include
  • 编译支持fastcgi版本的calcserver.cgi[5]
calcserver$ arm-linux-gnueabihf-g++ -o calcserver.cgi calcserver.cpp soapC.cpp soapcalcService.cpp /gsoap-source-path/gsoap/stdsoap2.cpp -DWITH_FASTCGI  -I/usr/local/arm-linux/include -I/fcgi-lib-path/fcgi/include -L/fcgi-lib-path/fcgi/usr/lib -lfcgi
  • fcgi-lib-path - 这个指向arm linux版的fcgi库
  • gsoap-source-path - 这个指向gsoap的源码路径`
  • 我们编译stdsoap2.cpp这个文件,而不去链接libsoap++.a
  • 定义WITH_FASTCGI

2.5 配置lighttpd

如果编译的是cgi版本,直接把编译好的calcserver.cgi放到cig-bin目录下即可。

如果是fastcgi版本,需要修改lighttpd配置文件,增加如下内容(前提lighttpd已经配置好支持fastcgi了):

fastcgi.server = (
  "calcserver.cgi" =>
  (( "socket" => "/tmp/fcgi.socket",
     "check-local" => "disable",
     "bin-path" => "/webSvr/web/cgi-bin/calcserver.cgi",
     "max-procs" => 1,
  ))
)

3 参考文档

  1. Apache Tutorial: Dynamic Content with CGI
  2. Getting Started with gSOAP
  3. gSoap missing stdsoap2.cpp, undefined reference to `soap_peek_element'
  4. Curl实现web serivce调试调用
  5. 19.32 FastCGI Support - genivia.com
  6. linux设备上的Onvif 实现4:成功编译gsoap 2.8.15 - blog.csdn
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,029评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,395评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,570评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,535评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,650评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,850评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,006评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,747评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,207评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,536评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,683评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,342评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,964评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,772评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,004评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,401评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,566评论 2 349

推荐阅读更多精彩内容