最近工作中需要将公司c++实现的人脸识别服务做成web服务,小伙伴推荐用gSoap,就找他来做网络代理,在生成通讯代码是-i选项让我很好奇。工作完成后,就随手试试,发现开发的代码省了好多,忍不住记录下来。
维基百科:gsoap是用于soap/XML web服务和通用xml数据绑定的c/c++软件开发工具包。
gSoap工具为任何类型的c/c++数据的xml序列化生成零拷贝开销的高效源代码。其中,Soap是传输协议,Xml是数据传输的格式。
通俗来讲:gSoap 工具可依据待提供服务接口的c/c++头文件(有固定格式)生成对应的wsdl文件以及负责数据打包,传输以及解包的c/c++底层代码。此时,开发人员可将自己的精力投入上层业务逻辑,甚至不需要了解soap协议。
下载什么的就不说了。
发布服务的流程:编写接口文件 -> wsdl以及底层通讯代码->将前文生成的代码嵌入到自己的人脸比对服务程序中。此处随便写个简单的测试接口。
服务器端:
1.编写接口文件:如lxx_test.h
//gsoap ns service name: lxx_test
//gsoap ns service namespace: http://localhost:8090/lxx_test.wsdl
//gsoap ns service location: http://localhost:8090
//gsoap ns service executable: lxx_test.cgi
//gsoap ns service encoding: encoded
//gsoap ns schema namespace: urn:lxx_test
int ns__test1(std::string input1,std::string &result);
此头文件提供了一个test1的接口,ns是命名空间(还没理清为什么这种格式),下划线是“ns__”两条,此文件格式很重要。注意://gsoap ns schema namespace:~urn:lxx_test,中的“~”相当于是空格,如果没有,会影响生成的wsdl文件的完整性(亲测)。
Localhost:可改为具体的ip.
2. 生成wsdl文件以及底层通讯代码
生成这些文件需要gsoap提供的工具:soapcpp2.exe,wsdl2h.exe(开发客户端时使用)。由于需要传参,我将这些步骤写到脚本文件里:
新建txt文件,并更名为make_wsdl.bat
编辑内容:
cd /d ./
soapcpp2.exe -S -i lxx_test.h
ping 127.0.0.1 -n 10 >nul
解释:
1) cd /d ./ ===》进入当前目录
2) soapcpp2.exe -S -i lxx_test.h ===》 Soapcpp2.exe的参数-S仅生成服务器端代码,-i生成c++代理(c++程序员使用方便,此处先使用代理类)。Soapcpp2.exe -h可查询全部选项。
3) ping 127.0.0.1 -n >nul ===》打印信息一闪而过,此句仅为了实现时延,好看清打印信息。
双击运行脚本之后,生成文件:
(下文参考http://www.mamicode.com/info-detail-1853229.html)
soapStub.h// soap的存根文件,定义了接口文件里里对应的远程调用模型
soapC.cpp,soapH.h//soap的序列和反序列代码,它已经包含了soapStub.h,
Lxx_test.nsmap//命名空间定义
soaplxx_testService.cpp,soaplxx_testService.h//服务器端的c++代码封装。
3.建c++工程,进行编程。
开发程序时需要gsoap包中提供的stdsoap2.h和stdsoap2.cpp这两个文件(提供一些基本的定义和声明)。
main.cpp
#include
#include "web_module\soapH.h"
#include "web_module\soaplxx_testService.h"
#include "web_module\lxx_test.nsmap"
//必须实现,否则不能通过http访问获取。
int http_get(struct soap *soap)
{
FILE *fd = fopen("web_module\\lxx_test.wsdl","rb");
if(!fd)
{
return 404;
}
soap->http_content="text/xml";
soap_response(soap,SOAP_FILE);
for(;;)
{
size_t r=fread(soap->tmpbuf,1,sizeof(soap->tmpbuf),fd);
if(!r)
{
break;
}
if(soap_send_raw(soap,soap->tmpbuf,r))
{
break;
}
}
fclose(fd);
soap_end_send(soap);
return SOAP_OK;
}
int main()
{
lxx_testService ws;//lxx_testService就是生成的服务端代理类
ws.fget = http_get;
while(1)
{
if(ws.run(8090))
{
ws.soap_stream_fault(std::cerr);
}
}
return 0;
}
//test1是生成的一个纯虚函数,需要我们自己实现
int lxx_testService::test1(const std::string& input1, std::string &result)
{
result.append("lxx is always a beautiful girl!\n");
return SOAP_OK;
}
4. 测试:
打开SoapUI工具:新建soap工程,并输入正确的wsdl地址。
点击绿色三角按钮,发送请求。返回结果如下图:
成功返回结果。