gsoap 使用方法
C/C++ 想使用 WebService ,那么非常好的一个选择就是 gsoap ,本文档针对 gsoap 的入门,对深入的层面不进行过多的探讨,关于 WebService 的概念和 gsoap 高级应用,会另外有文档涉及。 gsoap 在网上的资料比较少,我猜想可能的原因是 gsoap 在应用中大多使用 Java 或者 .net ,而 C/C++ 使用的比较少。多余的话就不赘述了。现在开始。 gsoap 下载: SourceForge.net 下载后,在 Linux 和 Windows 下的安装使用就不多赘述了。只要有一点关于开源软件的使用经验就足够了。 gsoap 主要的应用程序分为两个: wsdl2h 和 soapcpp2 。 wsdl2h 是将 wsdl 定义转换成 .h 文件的工具。主要有一些选项: -c 代表转化成 C 代码。 -s 代表不使用 STL ,取而代之需要在工程中包含 stdsoap2.h 和 stdsoap2.cpp 。这些在安装的源码中都可以找到。 -o file 代表指定输出文件名称。 通常情况下使用命令 wsdl2h –s xxx.wsdl 即可生成想要的 .h 文件。 ? soapcpp2 是生成源码的工具,从某种意义上来说, WebService 和 ICE 相当的相像。都是网络通信协议的封装方式,所不同的是 WebService 使用的是公开协议。没有特殊选项的情况下 ,gsoap 不需要依赖其他的链接库。 soapcpp2 的主要选项有: -S 代表生成客户端代码。 -C 代表生成服务端代码。 -L 代表不生成 soapClientLib/soapServerLib -c 代表仅生成 c 代码 -i 代表使用 Proxy 通常情况下使用命令 soapcpp2 –S/-C –L -i xxx.h ? 在编写客户端的时候,比较简单,分成两种方式:使用 Proxy 的方式相对来说,比较简单 ,Demo 源码如下: #include <iostream> #include "soapcurrentTimeProxy.h" #include "currentTime.nsmap" using namespace std; int main() { ??????? cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!! ??????? currentTimeProxy currentTime; ??????? int nRet=0; ????? ?? if(currentTime.currentTime(10,&nRet) == SOAP_OK) ??????????????? printf("Return %d/n",nRet); ??????? else ??????????????? currentTime.soap_stream_fault(std::cerr); ??????? return 0; } 有几个地方需要注意: 1.?????? 需要包含 XXX.nsmap 文件,这非常重要,这是表示 WebService 的语义所在。 2.?????? 这个 Demo 是使用 Proxy 的调用方式,即在 soapcpp2 使用了 -i 这个参数。 3.?????? 如果使用了 wsdl2h –s 参数,需要包含 stdsoap2.h 和 stdsoap2.cpp 。 4.?????? 请不要包含 soapClientLib/soapServerLib Client 端使用非 Proxy 的方式省略,这在网上到处都是,需要关注的点差不多。另外关于 WebService 访问地址的问题。在正常情况下, WebService 地址在 wsdl 中指定。但除了这种方式,还可以使用指定 Server 的 ip 和 port 的方式,在 soap 有个成员变量 endpoint ,填写这个参数就可以。 编成服务端的情况稍微多一点,之所以这样说,可以把 WebService 的服务端分成两种调用方式:一种是使用 gsoap 来做 Http Server ;另外一种使用 httpd 或者其他的东西来做 HttpServer ,而 gsoap 作为 cgi 。 Demo 如下: #include "soaptest2PortBindingObject.h" #include "test2PortBinding.nsmap" #include <iostream> ? using namespace std; int main() { ? ?????? cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!! ??????? struct soap soap; ??????? int m,s; // master and slave sockets ??????? soap_init(&soap); ??????? m = soap_bind(&soap,"10.130.15.133",80,100); ??????? if (m < 0) ?????????? ????? soap_print_fault(&soap,stderr); ??????? else ??????? { ??????????????? fprintf(stderr,"Socket connection successful: master socket = %d/n",m); ??????????????? for (int i = 1; ; i++) ??????????????? { ??????????????????????? s = soap_accept(&soap); ??????????????????????? if (s < 0) ??????????????????????? { ??????????????????????????????? soap_print_fault(&soap,stderr); ??????????????????????????????? break; ?????????????????????? } ??????????????????????? fprintf(stderr,"%d: accepted connection from IP=%d.%d.%d.%d socket=%d/n",i,(soap.ip>>24)&0xFF,(soap.ip>>16)&0xFF,(soap.ip>>8)&0xFF,soap.ip&0xFF,s); ??????????????????????? if (soap_serve(&soap) != SOAP_OK) // process RPC request ??????????????????????????????? soap_print_fault(&soap,stderr); // print error ??????????????????????? fprintf(stderr,"request served/n"); ??????????????????????? soap_destroy(&soap); // clean up class instances ??????????????????????? soap_end(&soap); // clean up everything and close socket ??????????????? } ????? ?? }???? ??????? return 0; }??????? 和 Client 不同的是,这里没有使用 Proxy 方式,这里省略了两个需要实现的接口函数。从接口调用来分析 Bind 是启动 httpServer 的端口监听。而 accept 是接受 WebService 请求。 Serve 是提供 WebService 服务。这是使用 gsoap 自己作为 httpServer ,这个程序起来的时候,就会在循环中不断接受请求,然后提供服务,也就是说这个程序是一直启动的,并在循环中提供服务。这个一个单线程的程序,也就是说,同时只能处理一个请求,在效率上不是最佳的。那么有两种方式可以处理,一是使用多线程来调用 Serve ;二是使用 httpd 来作为 httpServer 。下面就是这样一个 Demo: int main() { // create soap context and serve one CGI-based request: ??????? soap_serve(soap_new()); } 非常简单,一次调用就执行一次程序。相当于使用多进程来处理并发请求。而调度器是 httpd 。将这个程序放在 httpd 的 cgi 空间中就可以了。 最后的提示,不要轻易定义什么编译宏。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |