百度打开搜索gsoap,映入眼帘的第一栏便是gSOAP官网,进入不必详细阅读,观其大略。
大意是说gSOAP是一种编译工具,并且提供了一个SOAP/XML关于C/C++语言的实现,从而让C/C++语言研发web服务或客户端程式的工作变得轻松了很多,其他不必赘述。其实质是,使用C++的朋友,在实际开发过程中如果遇到需要通过WSDL访问对方WebService服务器或者客户端的情况下,可以采用gSOAP这种编译工具,将WebService的WSDL接口API编译为C/C++直接可以加入到工程调用的源码,方便直接生成WebService客户端/服务端。当然C++访问WebService服务端/客户端的方式可不止这一种,在windows下还可以使用Windows Web Services API和非托管com组件方式。
2.1 下载gSOAP
同样是在gSOAP官网,左侧Download,下载最新版本。https://sourceforge.net/projects/gsoap2/files/
当前最新版本为gsoap_2.8.80
2.2 安装gSOAP
将其解压到指定目录,我这里解压路径为 F:\gsoap_2.8.80。将 F:\gsoap_2.8.80\gsoap-2.8\gsoap\bin\win32 加入系统环境变量。
wsdl2h作用是编译wsdl路径或文件生成c/c++头文件。
wsdl2h -help查看帮助可得如下使用方法:
命令最后可以是WebService接口地址(例如:http://webservice.webxml.com.cn/WebServices/WeatherWS.asmx?WSDL)也可以是导出的.wsdl文件。
wsdl2h -o CustService.h CustService.wsdl
soapcpp2.exe的作用是根据头文件自动生成调用远程 SOAP服务的客户端代码(称为存根:Stub)和提供SOAP服务的框架代码外它也能从头文件生成WSDL文件(如果使用STL,需要从压缩包里找到stlvector.h放到soapcpp2.exe目录下,否则运行失败)。
soapcpp2 -help查看帮助可得如下使用方法:
soapcpp2 -i -C -x CustService.h 执行后报错如下。
需要将gSOAP安装目录下gsoap\import\soap12.h拷贝到工程目录。再次执行成功。
生成如下文件
将生成文件中的文件***.nsmap、soapC.cpp、***SoapProxy.cpp、***SoapProxy.h、soapH.h、soapStub.h以及gSOAP安装目录下gsoap\ stdsoap2.cpp和stdsoap2.h拷贝并添加到项目工程。
SoapClient.h
SoapClient.h
#ifndef _SOAP_CLIENT_H_
#define _SOAP_CLIENT_H_
#include
#include "classdef.h"
#include "soapCustServiceSoapProxy.h"
class CSoapClient
{
public:
CSoapClient();
virtual ~CSoapClient(void);
void SetServerURL(const CString &endpointRoot, const CString &actionRoot);
void StopServer();
//查询客户等级(此接口为了兼容老的接口程序,新的参考2)
bool IsVipCustomer(IsVipCustomerRequest &request,string &backStr);
//查询客户等级(此接口为了兼容新老叫号机存在)
bool IsVipCustomerNew(IsVipCustomerNewRequest &request,string &backStr);
//刷卡完成后得到排队号以后需要触发的接口(此接口用于向大堂经理推送消息用到)
bool CustomerAcceptedToMng(CustomerAcceptedToMngRequest &request,string &backStr);
//刷卡完成后得到排队号以后需要触发的接口(此接口用于向大堂经理推送消息用到,支持上传客户排队时候排队机拍摄的客户头像数据)此接口代替了接口3
bool CustomerAcceptedToMngImg(CustomerAcceptedToMngImgRequest &request,string &backStr);
//通知客户已经被柜面叫到号(此接口是在柜员按下叫号器是触发,用于返回给柜员相应的客户信息)
bool VipCustomerAccepted(VipCustomerAcceptedRequest &request,string &backStr);
//评价结果上报
bool AppraiseAccepted(AppraiseAcceptedRequest &request,string &backStr);
void ConvertUTF8ToANSI(const char* strUTF8,CString &strANSI);
void ConvertANSIToUTF8(CString &strANSI);
public:
CustServiceSoapProxy m_custServiceSoapProxy;
string endpoint_root;
string action_root;
};
#endif // _SOAP_CLIENT_H_
SoapClient.cpp
// SoapClient.cpp
#include "SoapClient.h"
#include "CustServiceSoap.nsmap"
#include
#include "stdafx.h"
using namespace std;
CSoapClient::CSoapClient()
{
CString strModule;
GetModuleFileName(NULL, strModule.GetBuffer(MAX_PATH), MAX_PATH);
//注:使用该API函数得到的是程序文件完整路径文件名,去掉文件名后才是路径。
strModule.ReleaseBuffer();
int pos = strModule.ReverseFind('\\');
CString strDir;
strDir = strModule.Left(pos);
if( strDir.Right(1) != "\\" )
{
strDir += "\\" ;
}
CString strIniDir = strDir + ("connconfig.ini");
char rootEndpoint[MAX_PATH]={0};
char rootAction[MAX_PATH]={0};
endpoint_root.clear();
action_root.clear();
GetPrivateProfileString(_T("Third"), _T("endpoint_root"),"",rootEndpoint,MAX_PATH,strIniDir);
GetPrivateProfileString(_T("Third"), _T("action_root"),"",rootAction,MAX_PATH,strIniDir);
endpoint_root = rootEndpoint;
action_root = rootAction;
m_custServiceSoapProxy.soap->recv_timeout = 2;//接收超时(秒)
m_custServiceSoapProxy.soap->send_timeout = 2;//发送超时(秒)
m_custServiceSoapProxy.CustServiceSoapProxy_init(SOAP_C_UTFSTRING, SOAP_C_UTFSTRING);
}
CSoapClient::~CSoapClient(void)
{
}
void CSoapClient::SetServerURL(const CString &endpointRoot, const CString &actionRoot)
{
//web_ROOTUrl = web_root + "/services/RestMakeReservationService";
//m_custServiceSoapProxy.soap_endpoint = (char*)web_ROOTUrl.GetBuffer(0);
}
void CSoapClient::StopServer()
{
m_custServiceSoapProxy.destroy(); /* clean up mem */
}
bool CSoapClient::IsVipCustomer(IsVipCustomerRequest &request,string &backStr)
{
if(endpoint_root.empty() || action_root.empty())
{
write_log(LV_INFO,"后台参数没配置好,有空值");
AfxMessageBox("请先配置后台好参数.");
return false;
}
string endpointRootStr = endpoint_root + "/e-ccs/webservice/CustService.asmx";
string actionRootStr = action_root + "/custserv/IsVipCustomer";
_ns1__IsVipCustomer isVipCustomer;
_ns1__IsVipCustomerResponse isVipCustomerResponse;
char buffer[33]={0};
string type;
type = itoa(request.cardType,buffer,10);
isVipCustomer.cardType = &type;
isVipCustomer.cardNbr = &request.cardNbr;
isVipCustomer.deviceNbr = &request.deviceNbr;
//调用IsVipCustomer接口
//m_custServiceSoapProxy.IsVipCustomer(endpointRootStr.c_str(),actionRootStr.c_str(),&isVipCustomer,isVipCustomerResponse);
if (m_custServiceSoapProxy.soap->error){
std::ostringstream stream;
m_custServiceSoapProxy.soap_stream_fault(stream);
backStr = stream.str();
return false;
}
else
{
}
return true;
}
bool CSoapClient::IsVipCustomerNew(IsVipCustomerNewRequest &request,string &backStr)
{
//
return true;
}
bool CSoapClient::CustomerAcceptedToMng(CustomerAcceptedToMngRequest &request,string &backStr)
{
if(endpoint_root.empty() || action_root.empty())
{
write_log(LV_INFO,"后台参数没配置好,有空值");
AfxMessageBox("请先配置后台好参数.");
return false;
}
string endpointRootStr = endpoint_root + "/e-ccs/webservice/CustService.asmx";
string actionRootStr = action_root + "/custserv/CustomerAcceptedToMng";
_ns1__CustomerAcceptedToMng customerAcceptedToMng;
_ns1__CustomerAcceptedToMngResponse customerAcceptedToMngResponse;
customerAcceptedToMng.cardType = &request.cardType;
customerAcceptedToMng.cardNbr = &request.cardNbr;
customerAcceptedToMng.deviceNbr = &request.deviceNbr;
customerAcceptedToMng.queueNbr = &request.queueNbr;
//调用CustomerAcceptedToMng接口
//m_custServiceSoapProxy.CustomerAcceptedToMng(endpointRootStr.c_str(),actionRootStr.c_str(),&customerAcceptedToMng,customerAcceptedToMngResponse);
if (m_custServiceSoapProxy.soap->error){
std::ostringstream stream;
m_custServiceSoapProxy.soap_stream_fault(stream);
backStr = stream.str();
return false;
}
else
{
}
return true;
}
bool CSoapClient::CustomerAcceptedToMngImg(CustomerAcceptedToMngImgRequest &request,string &backStr)
{
//
return true;
}
bool CSoapClient::VipCustomerAccepted(VipCustomerAcceptedRequest &request,string &backStr)
{
if(endpoint_root.empty() || action_root.empty())
{
write_log(LV_INFO,"后台参数没配置好,有空值");
AfxMessageBox("请先配置后台好参数.");
return false;
}
string endpointRootStr = endpoint_root + "/e-ccs/webservice/CustService.asmx";
string actionRootStr = action_root + "/custserv/VipCustomerAccepted";
_ns1__VipCustomerAccepted vipCustomerAccepted;
_ns1__VipCustomerAcceptedResponse vipCustomerAcceptedResponse;
vipCustomerAccepted.deviceNbr = &request.deviceNbr;
vipCustomerAccepted.queueNbr = &request.queueNbr;
vipCustomerAccepted.tellerNbr = &request.tellerNbr;
vipCustomerAccepted.cardType = &request.cardType;
vipCustomerAccepted.cardNbr = &request.cardNbr;
//调用VipCustomerAccepted接口
//m_custServiceSoapProxy.VipCustomerAccepted(endpointRootStr.c_str(),actionRootStr.c_str(),&vipCustomerAccepted,vipCustomerAcceptedResponse);
if (m_custServiceSoapProxy.soap->error){
std::ostringstream stream;
m_custServiceSoapProxy.soap_stream_fault(stream);
backStr = stream.str();
return false;
}
else
{
}
return true;
}
bool CSoapClient::AppraiseAccepted(AppraiseAcceptedRequest &request,string &backStr)
{
if(endpoint_root.empty() || action_root.empty())
{
write_log(LV_INFO,"后台参数没配置好,有空值");
AfxMessageBox("请先配置后台好参数.");
return false;
}
string endpointRootStr = endpoint_root + "/e-ccs/webservice/CustService.asmx";
string actionRootStr = action_root + "/custserv/AppraiseAccepted";
_ns1__AppraiseAccepted appraiseAccepted;
_ns1__AppraiseAcceptedResponse appraiseAcceptedResponse;
appraiseAccepted.deviceNbr = &request.deviceNbr;
appraiseAccepted.queueNbr = &request.queueNbr;
appraiseAccepted.tellerNbr = &request.tellerNbr;
appraiseAccepted.appraiseGrade = &request.appraiseGrade;
//调用AppraiseAccepted接口
//m_custServiceSoapProxy.AppraiseAccepted(endpointRootStr.c_str(),actionRootStr.c_str(),&appraiseAccepted,appraiseAcceptedResponse);
if (m_custServiceSoapProxy.soap->error){
std::ostringstream stream;
m_custServiceSoapProxy.soap_stream_fault(stream);
backStr = stream.str();
return false;
}
else
{
}
return true;
}
void CSoapClient::ConvertUTF8ToANSI(const char* strUTF8,CString &strANSI) //
{
int nLen = ::MultiByteToWideChar(CP_UTF8,MB_ERR_INVALID_CHARS,(LPCTSTR)strUTF8,-1,NULL,0); //返回需要的unicode长度
WCHAR * wszANSI = new WCHAR[nLen+1];
memset(wszANSI, 0, nLen * 2 + 2);
nLen = MultiByteToWideChar(CP_UTF8, 0, (LPCTSTR)strUTF8, -1, wszANSI, nLen); //把utf8转成unicode
nLen = WideCharToMultiByte(CP_ACP, 0, wszANSI, -1, NULL, 0, NULL, NULL); //得到要的ansi长度
char *szANSI=new char[nLen + 1];
memset(szANSI, 0, nLen + 1);
WideCharToMultiByte (CP_ACP, 0, wszANSI, -1, szANSI, nLen, NULL,NULL); //把unicode转成ansi
strANSI = szANSI;
delete wszANSI;
delete szANSI;
}
void CSoapClient::ConvertANSIToUTF8(CString &strANSI)
{
int nLen = ::MultiByteToWideChar(CP_ACP,MB_ERR_INVALID_CHARS,(LPCTSTR)strANSI,-1,NULL,0);
if(nLen>1)
{
WCHAR * wszUTF_8 = new WCHAR[nLen+1];
memset(wszUTF_8, 0, nLen * 2 + 2);
nLen = MultiByteToWideChar(CP_ACP, 0, (LPCTSTR)strANSI, -1, wszUTF_8, nLen);
nLen = WideCharToMultiByte(CP_UTF8, 0, wszUTF_8, -1, NULL, 0, NULL, NULL);
char *szUTF8=new char[nLen + 1];
memset(szUTF8, 0, nLen + 1);
WideCharToMultiByte(CP_UTF8, 0, wszUTF_8, -1, szUTF8, nLen, NULL,NULL);
strANSI = szUTF8;
delete wszUTF_8;
delete szUTF8;
}
}