VC++6.0 用gSoap客户端访问WebService

1、安装gSOAP

首先我们到 http://sourceforge.net/project/showfiles.php?group_id=52781链接去下载gSoap工具集gSoap工具集不需要安装,直接解压就可以了。在gsoap-2.8\gsoap\bin\win32目录下我们可以看到两个可执行文件:

soapcpp2.exe: gSoap编译器,编译头文件生成服务器和客户端都需要的 c/c++文件。
wsdl2h.exe: 编译wsdl文件生成c/c++头文件。

soapcpp2.exe和wsdl2h.exe的参数的意思自己在命令行输入 soapcpp2 -h来查看

2、根据WSDL生成 .h文件
我用搜索中国邮政编码的WebService来做例子,网址是http://www.webxml.com.cn/WebServices/ChinaZipSearchWebService.asmx。
2.1、在命令行执行:

wsdl2h -s -o AlyPostCode.h http://www.webxml.com.cn/WebServices/ChinaZipSearchWebService.asmx?wsdl
生成 AlyPostCode.h文件,参数中使用 -s说明不要使用stl代码, -o后面接着的是根据wsdl生产的头文件名称

关于wsdl2h.exe中各个参数的含义如下:

-o 文件名,指定输出的头文件名称
-n 命名空间前缀,代替默认的ns
-c 产生纯C代码,否则是C++代码
-s 不要使用stl代码
-t 文件名,指定type map文件,默认为typemap.dat
-e 禁止为enum成员加上命名空间前缀
3、执行:soapcpp2.exe   -C -L -i -x  -I[import的路径] AlyPostCode .h

即可以生成客户端存根程序和框架了。
-C 选项是只生成客户端的,默认是生成客户端和服务器端的,如果你在程序中使用了vector还要加上 –limport选项来指定import的路径,或者把需要的文件从gsoap-2.8\gsoap\import拷贝到编译目录下。

soapcpp2.exe各个参数的含义如下:

-C 仅生成客户端代码
-S 仅生成服务器端代码 
-L 不要产生soapClientLib.c和soapServerLib.c文件  
-c 产生纯C代码,否则是C++代码(与头文件有关)  
-I 指定import路径
-x 不要产生XML示例文件 
-i 生成C++包装,客户端为xxxxProxy.h(.cpp),服务器端为xxxxService.h(.cpp)

soapClient.cpp:编译客户端需要的存根例程。
soapC.cpp,soapH.h:用来序列化和反序列化C/C++不同数据类型。
soapServer.cpp: 编译服务器端需要的存根例程。
soapXXXProxy.h: 生成的代理类的头文件,使用代理类时需要此文件。
本程序为soapChinaZipSearchWebServiceSoapProxy.h。

上面的命令执行完成后,会生产下面的6个文件,如下:

soapC.cpp
soapChinaZipSearchWebServiceSoapProxy.cpp
soapChinaZipSearchWebServiceSoapProxy.h
soapH.h
soapStub.h
ChinaZipSearchWebServiceSoap.nsmap
到此,所需的文件准备完毕。

4、建立基于对话框的MFC工程

4.1、把第三步生产的6个文件和gsoap-2.8\gsoap目录下的stdsoap2.cpp\stdsoap2.h一共8个文件添加到工程

4.2、给工程添加socket支持 Project -> Setting  在对话框中的Link选项卡种 Object/library modules:下添加ws2_32.lib

4.3、设置soapChinaZipSearchWebServiceSoapProxy.cpp\stdsoap2.cpp\soapC.cpp三个文件不适用预编译头,方法:Project->Setting 选中上述的3个文件在C/C++选项卡中的Category 中选择Precompiled Headers,然后点击下面的单选框Not using precompiled headers。

4.4、在Stdafx.h文件中增加我们刚才加入到工程中的头文件,如下:

#include "soapChinaZipSearchWebServiceSoapProxy.h"
#include "ChinaZipSearchWebServiceSoap.nsmap"
4 .5、顺利的话,编译没有错误。

4.6、在对话框上增加测试按钮,单击按钮,请求邮编所对应的地址,代码如下:

void CMy123Dlg::OnButton1() 
{
	// TODO: Add your control notification handler code here
	ChinaZipSearchWebServiceSoapProxy zipProxy("http://www.webxml.com.cn/WebServices/ChinaZipSearchWebService.asmx", SOAP_C_UTFSTRING);
	_ns1__getAddressByZipCode	zipCode;
	CString strCode = "116000";
	zipCode.theZipCode = strCode.GetBuffer(0);
	CString strUserID = "";
	zipCode.userID = strUserID.GetBuffer(0);
	_ns1__getAddressByZipCodeResponse	zipAddr;
	
	int result = zipProxy.getAddressByZipCode(&zipCode, &zipAddr);
	if (SOAP_OK != result)
	{
		AfxMessageBox(_T("出错了"));
	}
	else
	{
		string strAddr = zipAddr.getAddressByZipCodeResult->__any;///< 获取邮编对应的地址
		wchar_t* ch = MulityByteToWideChar(zipAddr.getAddressByZipCodeResult->__any);
		AfxMessageBox(CString(ch));
		AfxMessageBox(CString(strAddr.c_str()));
	}
}
4.7、传回的数据为乱码,下面的函数把它转化成UTF8,以便正常显示中文:

wchar_t* CMy123Dlg::MulityByteToWideChar(char* str)
{
	DWORD dwNum = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
	wchar_t *pwText = new wchar_t[dwNum];
	MultiByteToWideChar(CP_UTF8, 0, str, -1, pwText, dwNum); 
	return pwText;
}


4.8、圆满完成......


4.9、调用webService时,传给相关函数的参数和和获取的数据通常需要进行编码类型的转换,在Visual C++6.0编程环境下,常用的转换函数如下:

UnicodeToUTF8函数具体实现如下:

char* UnicodeToUTF8(const wchar_t *str)
{
    char * result;  
    int textlen = 0;  
    // wide char to multi char   
    textlen = WideCharToMultiByte( CP_UTF8,    0,    str,    -1,    NULL, 0, NULL, NULL );  
    result =(char *)malloc((textlen+1)*sizeof(char));  
    memset( result, 0, sizeof(char) * ( textlen + 1 ) );  
    WideCharToMultiByte( CP_UTF8, 0, str, -1, result, textlen, NULL, NULL );  
    return result; 
}
UTF8ToUnicode函数的具体实现如下:

wchar_t* UTF8ToUnicode(const char *str)
{
    int textlen = 0;  
    wchar_t * result;  
    textlen = MultiByteToWideChar( CP_UTF8, 0, str,-1,    NULL,0 );    
    result = (wchar_t *)malloc((textlen+1)*sizeof(wchar_t));    
    memset(result,0,(textlen+1)*sizeof(wchar_t));    
    MultiByteToWideChar(CP_UTF8, 0,str,-1,(LPWSTR)result,textlen );    
    return    result;
}

在Visual c++ 6.0环境中,当要从webService端获取数据时,通常会给wsdl中描述的函数传递参数,该参数要是中文的话,需要从unicode转换为Unicode,就需要调用上面提到的函数UnicodeToUTF8,该函数需要wchar_t类型的参数,我们得到的CString类型的参数要转换为wchar_t类型的参数,需要CString类的成员函数AllocSysString,具体使用方法如下:

((CWnd*)GetDlgItem(IDC_EDIT_USERNAME))->GetWindowText(strName);
strTDJInfo.strName = UnicodeToUTF8(strName.AllocSysString());

((CWnd*)GetDlgItem(IDC_EDIT_ACCOUNT))->GetWindowText(strAccount);
strTDJInfo.strAccount = UnicodeToUTF8(strAccount.AllocSysString());

----------------------------------------------------------------------------------------------------------------

gSoap中文乱码问题相关。

1、wchar_t类型简介:

wchar_t是C/C++的字符数据类型,是一种扩展的字符存储方式,wchar_t类型主要用在国际化程序的实现中,但它不等同于unicode编码。unicode编码的字符一般以wchar_t类型存储。

char是8位字符类型,最多只能包含256种字符,许多外文字符集所含的字符数目超过256个,char型无法表示。wchar_t数据类型一般为16位或32位,但不同的C或C++库有不同的规定,如GNU Libc规定wchar_t为32位[1],总之,wchar_t所能表示的字符数远超char型。标准C++中的wprintf()函数以及iostream类库中的类和对象能提供wchar_t宽字符类型的相关操作。



你可能感兴趣的:(VC++6.0 用gSoap客户端访问WebService)