C++调用webservice
最近要利用C++调用WebService接口,中间工具是gSoap,IDE:VS2010,WebService接口:http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx?wsdl
关于Soap,它是一种简单对象访问协议,是一种轻量的、简单的、基于 XML 的协议,它被设计成在 WEB 上交换结构化的和固化的信息。它是一种通信协议,用于Web应用程序之间的因特网通信,它提供一组不受平台和语言限制的方法使应用程序得以相互之间进行Intertnet通信。而gSoap可以看做是对soap的一个实现封装,它隐藏了在调用WebService中的大量实现细节,使得C++调用WebService变得较为简单。它提供编译工具(实际就是针对接口的WSDL生成类文件),然后引入工程操作生成类即可达到访问WebService接口的目的。仔细查看生成的文件就会发现生成的类与WebService接口的WSDL文件实际相对应的。
WSDL,最初弄的WSDL的时候被这个WSDL弄的焦头烂额的。这个文件实际上就是WebService的对外接口文件,它是一个XML文件,描述了WebService接口的外部方法和抽象方法,以及各协议下的相关调用,是一个用来描述Web服务和说明如何与Web服务通信的XML语言,为用户提供详细的接口说明书。对于WSDL文件,只需要在浏览器中打开,即可查看到WebService接口的外部供调用的方法。
对于Soap,gSoap,WSDL就大致介绍到这里,这里记录如何在C++中调用WebService接口,以http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx?wsdl为例,一个查询手机号码归属地的WebService接口。
下载gSoap-2.8版本解压放置D盘,在命令行下进入gSoap-2.8/gsoap/bin/win32目录。网络上有不少gSoap的下载,读者可自行下载。
然后运行命令:wsdl2h -s -o service1.h http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx?wsdl,这时在wsdl2h.exe目录下生成service1.h头文件,然后运行命令:soapcpp2 -C -x service1.h生成其他的文件,在我的目录下生成了这些文件:
第一个红色圈圈里面都是生成的文件,要全部引入工程,其中soapClientLib.cpp文件无用,不引入,引入会报错。然后将gSoap-2.8/目录喜爱的stdsoap2.h/cpp也要引入工程。
取消soapC.cpp,soapClient.cpp,stdsoap2.cpp这三个文件的预编译头,在stdafx.h文件中增加#include"MobileCodeWSSoap.nsmap"
从webService获取数据:
- void callService()
- {
- LOG_TRACE_METHOD();
- struct soap soap;
- char* str="";
- wchar_t* str_1 = NULL;
- int b=0;
- class _ns1__getMobileCodeInfoResponse resultStr;
- class _ns1__getMobileCodeInfo a;
- soap_init(&soap);
- soap_set_mode(&soap,SOAP_C_MBSTRING);
- a.mobileCode = ConvAnsiToUtf8("18600960941");
- soap_call___ns2__getMobileCodeInfo(&soap,"http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx?wsdl","",&a,&resultStr);
- if (soap.error)
- {
- soap_print_fault(&soap, stderr);
- }
- else
- {
- str = resultStr.getMobileCodeInfoResult;
- std::cout << str << endl;
- }
- soap_destroy(&soap);
- soap_end(&soap);
- soap_done(&soap);
- }
void callService() { LOG_TRACE_METHOD(); struct soap soap; char* str=""; wchar_t* str_1 = NULL; int b=0; class _ns1__getMobileCodeInfoResponse resultStr; class _ns1__getMobileCodeInfo a; soap_init(&soap); soap_set_mode(&soap,SOAP_C_MBSTRING); a.mobileCode = ConvAnsiToUtf8("18600960941"); soap_call___ns2__getMobileCodeInfo(&soap,"http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx?wsdl","",&a,&resultStr); if (soap.error) { soap_print_fault(&soap, stderr); } else { str = resultStr.getMobileCodeInfoResult; std::cout << str << endl; } soap_destroy(&soap); soap_end(&soap); soap_done(&soap); }
运行后如图:
我们可以查看http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx?wsdl,查看该xml文件可看到字符编码是UTF8的,因此传递给接口的参数需要转换到UTF8才可,ConvAnsiToUtf8()是转换函数。gsoap 的 核心内部是入和出都是UTF8编码的,由于中文是多字节的,所以将多字节的按照UTF8转换,最终结果就是乱码。正确的方式应该是:soap_set_mode(&soap,SOAP_C_MBSTRING);这样中文便不会乱码,可正常返回。