Posted on 2010-08-22 18:04
roy 閱讀(2182)
評論(0) 編輯 收藏 引用 所屬分類:
C/C++
- 電信provisioning系統中,常常需要與遠程服務器實時交換一些數據,以完成用戶的請求。由于簡單對象訪問協議(Simple Object Access Protocol, SOAP)的流行,許多涉及到第三方的應用,我們一般都比較樂意使用SOAP來開發。不過,由于可能涉及到公司的機密,本系列教程的開發實例盡量采用在網上已經公開的Web Service資源。
-
- 上一節,講解了用iconv解決gSOAP輸出的中文文本亂碼的問題。在本節中,我們用一個天氣預報客戶端的例子,簡述一下gSOAP輸入的中文文本亂碼的問題。
-
- Webxml.com.cn提供的天氣預報web服務,endpoint地址是:http://webservice.webxml.com.cn/WebServices/WeatherWebService.asmx,大家可以點擊進去,查看一下該服務的所有對外提供的接口。其中,利用getWeatherbyCityName接口,可以按給定的城市名字查詢該城市的天氣預報,如果輸入的城市名字不能識別,將統一返回北京的天氣預報。
-
- 根據前三節的內容,我們可以很快地準備好其客戶端存根程序:
- 1. mkdir –p weather
- 2. cd weather
- 3. ../wsdl2h -c -o weather.h
- http://webservice.webxml.com.cn/WebServices/WeatherWebService.asmx?wsdl
- 4. ../../bin/linux386/soapcpp2 –C –L –x weather.h
-
- 由于程序并不復雜,直接給出其源代碼:
#include <iconv.h>
#include "soapH.h"
#include "WeatherWebServiceSoap12.nsmap"
#define OUTPUT_LEN 2048
int conv_charset(const char *dest, const char *src, char *input, size_t ilen, char *output, size_t olen) {
iconv_t conv = iconv_open(dest, src);
if ( conv == (iconv_t) -1 )
return -1;
memset(output, 0, olen);
if ( iconv(conv, &input, &ilen, &output, &olen) )
return -1;
iconv_close(conv);
return 0;
}
int main(int argc, char **argv) {
if ( argc != 2 && argc != 3 ) {
printf("Usage: %s city_name [end_point]\n", argv[0]);
exit(-1);
}
struct soap soap;
soap_init(&soap);
soap_set_mode(&soap, SOAP_C_UTFSTRING);
struct _ns1__getWeatherbyCityName request;
struct _ns1__getWeatherbyCityNameResponse response;
size_t ilen = strlen(argv[1]);
char output[OUTPUT_LEN];
if ( conv_charset("UTF-8", "GBK", argv[1], ilen, output, OUTPUT_LEN) )
request.theCityName = argv[1];
else
request.theCityName = output;
char *endpoint = NULL;
if ( argc == 3 )
endpoint = argv[2];
if ( soap_call___ns3__getWeatherbyCityName(&soap, endpoint, NULL, &request, &response) == SOAP_OK ) {
int element_counter = response.getWeatherbyCityNameResult->__sizestring;
int i = 0;
for ( i = 0; i < element_counter; i++ ) {
switch ( i ) {
case 0 : printf("Province : "); break;
case 1 : printf("City : "); break;
case 2 : printf("City code : "); break;
case 3 : printf("City pic. name : "); break;
case 4 : printf("Timestamp : "); break;
case 5 : printf("Temp. of today : "); break;
case 6 : printf("Summary : "); break;
case 7 : printf("Wind : "); break;
case 8 : printf("Icon 1 : "); break;
case 9 : printf("Icon 2 : "); break;
case 10 : printf("Description : "); break;
case 11 : printf("Reserved : "); break;
case 12 : printf("Temp. of tomorrow : "); break;
case 13 : printf("Summary : "); break;
case 14 : printf("Wind : "); break;
case 15 : printf("Icon 1 : "); break;
case 16 : printf("Icon 2 : "); break;
case 17 : printf("Temp. of af. tmr. : "); break;
case 18 : printf("Summary : "); break;
case 19 : printf("Wind : "); break;
case 20 : printf("Icon 1 : "); break;
case 21 : printf("Icon 2 : "); break;
case 22 : printf("Introduction : "); break;
default : break;
}
ilen = strlen(response.getWeatherbyCityNameResult->string[i]);
if ( conv_charset("GBK", "UTF-8", response.getWeatherbyCityNameResult->string[i], ilen, output, OUTPUT_LEN) )
printf("%s\n", response.getWeatherbyCityNameResult->string[i]);
else
printf("%s\n", output);
}
}
else {
soap_print_fault(&soap, stderr);
}
soap_destroy(&soap);
soap_end(&soap);
soap_done(&soap);
return 0;
}
- 編譯命令是:gcc -O2 -o weather weather.c soapC.c soapClient.c ../../stdsoap2.c -I../.. -L../.. –lgsoap
-
基本上與上一節的股票信息客戶端差不多,唯一不同的是,作為輸入參數的城市名字,首先需要iconv轉換編碼,從GBK轉到UTF-8,才可以提交給服務端。各位可以試一下,不作轉換的話,無論輸入什么,服務端只會返回北京的天氣預報,因為傳入的參數在服務端產生了亂碼。
以下為正常的執行結果,輸入廣州,可以得到廣州的天氣預報:

-
- 如上圖,最后一段的介紹也出現了亂碼,不過我認為這是putty的問題,行末的最后一個全角字符,如果只能顯示一半的話,下一行開始將產生亂碼,如果再遇到一個半角字符,又能顯示正常了。
- http://blog.csdn.net/yui/archive/2010/07/23/5758906.aspx