使用gSOAP构建Web服务与客户端交互
基于WSDL文件生成C++客户端代理类,需先通过wsdl2h工具提取接口定义:
wsdl2h -s -o MyHeader.h http://www.genivia.com/calc.wsdl
参数 -s 表示不使用STL,-o 指定输出头文件。
接着使用soapcpp2生成客户端代码:
soapcpp2 -i -C MyHeader.h
-i 生成包含客户端逻辑的代理类,-C 表示仅生成客户端代码。此过程可能因缺少依赖文件失败,需确保包含以下核心文件:soap12.h、stdsoap2.h、stdsoap2.cpp。
在应用程序中调用生成的代理类访问远程服务:
#include "soapWebService1SoapProxy.h"
#include "WebService1Soap.nsmap"
int main()
{
WebService1SoapProxy service;
_tempuri__GetSum request;
_tempuri__GetSumResponse response;
request.a = 1;
request.b = 5;
if (service.GetSum(&request, &response) == SOAP_OK)
std::cout << "1 + 5 = " << response.GetSumResult << std::endl;
else
service.soap_stream_fault(std::cerr);
service.destroy();
return 0;
}
若编译时报错 LNK2001: 无法解析的外部符号 _namespaces,可在 stdsoap2.h 中添加:
#ifndef WITH_NONAMESPACES
#define WITH_NONAMESPACES
#endif
构建独立运行的Web服务端
定义服务接口描述文件 currentTime.h:
// gsoap ns service name: currentTime
// gsoap ns service namespace: urn:currentTime
// gsoap ns service location: http://www.yourdomain.com/currentTime.cgi
int ns__currentTime(time_t& response);
生成服务端代码:
soapcpp2 -i -S currentTime.h
实现服务逻辑并启动监听:
#include "soapcurrentTimeService.h"
#include "currentTime.nsmap"
int main()
{
currentTimeService server;
while (server.run(65533) != SOAP_TCP_ERROR)
{
server.soap_stream_fault(std::cerr);
}
return 0;
}
int currentTimeService::currentTime(time_t& response)
{
response = time(0);
return SOAP_OK;
}
编译时需链接:currentTime.cpp、soapC.cpp、soapcurrentTimeService.cpp、stdsoap2.cpp。
C# 客户端调用gSOAP服务
使用Visual Studio自带的wsdl.exe工具从WSDL生成C#代码:
wsdl.exe currentTime.wsdl
生成 currentTime.cs 后加入项目,修改默认地址:
public picture() {
this.Url = "http://localhost:65432/picture.cgi"; // 替换为实际服务地址
}
传输二进制数据(如图片)
服务端将图像编码为Base64字符串发送:
int pictureService::picture(struct picdata &picture)
{
char *data = nullptr;
unsigned int size = 0;
std::ifstream file("chicken.jpg", std::ios::binary);
if (file.is_open())
{
file.seekg(0, std::ios::end);
size = file.tellg();
file.seekg(0, std::ios::beg);
data = new char[size];
if (!data) return SOAP_ERR;
file.read(data, size);
file.close();
}
picture.data = base64_encode((unsigned char*)data, size);
delete[] data;
return SOAP_OK;
}
客户端接收并解码保存图像:
picture pic = new picture();
picture1 pic1 = new picture1();
pictureResponse res = pic.Callpicture(pic1);
string base64Data = res.picture.data;
byte[] imageBytes = Convert.FromBase64String(base64Data);
using (FileStream fs = new FileStream(@"D:\picture.jpg", FileMode.OpenOrCreate))
{
fs.Write(imageBytes, 0, imageBytes.Length);
}
上述方案适用于原型验证,生产环境建议优化内存管理与错误处理机制。