天天看點

gsoap的編繹和移植

基于webservice協義,實作一個簡單的天氣預報

    這些時間在玩黑莓,黑莓上有一款天氣預報的小軟體。個人出于好奇,想要研究一下該功能的實作過程。

    網絡方面的程式一直很少接觸,算是一個盲點。是以剛開始, 理所當然的認為該功能的實作過程與ntp協定相似,都是用戶端,建立socket,與伺服器建立連接配接, 用戶端

發送帶有地點資訊的資料到伺服器,伺服器傳回包括該城市天氣資訊的資料到用戶端, 客戶解析資料,得到天氣資訊。

    真正開始着手查詢相關的資料時,才知道網絡對些查詢服務協定已有明确的名字名義--webservice,以前似乎好像有聽過此概念。啥叫 webservice,字面上可以了解為網絡服務。

一個很簡單的例子來說明一下,什麼是webservice。計算1+1等于幾?用戶端與webservice伺服器建立連接配接, 告訴伺服器端我想要得到1+1 的結果, 伺服器進行運算,傳回計算結果給用戶端。

這不就是目前很火,引無數it巨頭竟腰的雲計算嗎?目前,在網絡上這樣的伺服器很多,有查詢股票資訊的, 有查詢天氣的,五花八門。

    寫到webservice ,不得不提到gsoap。gsoap 更像是一個代碼生成器的工具,我們完全可以不利用gsoap,按照webservice的協義,個人編寫全部的代碼。有了gsoap 工具一切都好辦,

gsoap用戶端和伺服器的開發工作大為簡化。下面重點寫寫如何用gsoap 完成一個天氣預報用戶端的開發全過程。

    1 下載下傳gsoap,并解壓到linux目錄下(/home/code/ ),下載下傳位址為http://sourceforge.net/projects/gsoap2/files/

      #cd /home/code

      #unzip gsoap_2.8.0.zip 

    2 解壓後,生成gsoap-2.8。一般情況下, 從網絡上下載下傳開發包,在本地怎麼都得先./configure 再 make一下,但是gsoap更像是一個工具包,解壓後,可以直接使用包裡面的工具,也就是soapcpp2和wsdl2h這兩個工具,

     不同的平台對應的工具是不一樣,目前gsoap支援的平台有linux386,macosx ,win32,我所使用主機環境為fedora-9,是以應使用linux386下的工具。

     #cd /home/code/gsoap-2.8/gsoap/bin/linux386

     

    3 建立一個新的目錄,命名為weather

      #mkdir weather

    4 利用gsoap 工具生成webserice 協義代碼,wsdl2h從伺服器下載下傳頭檔案,soapcpp2相當于代碼生成品,根據頭檔案生成相應的.c檔案和.nsmap檔案。

      #../wsdl2h -c -o weather.h http://www.ayandy.com/Service.asmx?WSDL

      注 -c 生成.c檔案,相對于C++,個人還是一直偏好于C語言。

      #../soapcpp2 -x -C -c weather.h

      -x  不生成xml檔案

      -C 隻生成用戶端相關代碼

    5 拷貝/home/code/gsoap-2.8/gsoap目錄下的stdsoap2.h stdsoap2.c 兩個檔案到 weather目錄下。

      #cp /home/code/gsoap-2.8/gsoap/stdsoap2.h ./

      #cp /home/code/gsoap-2.8/gsoap/stdsoap2.c  ./

    6 編寫用戶端程式,也就是調用剛剛生成代碼中接口函數。

      #vim weather.c

#include<stdio.h>

#include"soapH.h"

#include"ServiceSoap.nsmap"

#define

CITY_NAME "北京"

int main(int argc, char *argv[])

{

struct soap soap;

int ret = 0;

int element = 0;

int i = 0;

soap_init(&soap);

soap_set_mode(&soap, SOAP_C_UTFSTRING);

soap.mode |= SOAP_C_UTFSTRING;

struct _ns1__getWeatherbyCityName cityname;

struct _ns1__getWeatherbyCityNameResponse response;

cityname.theCityName = CITY_NAME;

cityname.theDayFlag = 0;

if(soap_call___ns3__getWeatherbyCityName(&soap, NULL, NULL,

&cityname, &response) == SOAP_OK)

{

printf("get weather ok !/n");

element = response.getWeatherbyCityNameResult->__sizestring;

for(i = 0; i < element; i++)

{

printf("i(%d), string(%s)/n", i,

response.getWeatherbyCityNameResult->string[i]);

}

}

else

{

printf("soap_call___ns3__getWeatherbyCityName failed!/n");

}

soap_destroy(&soap);

soap_end(&soap);

soap_done(&soap);

return 0;

}

6 編寫Makefile

#CROSS_COMPILER:=

CC:=$(CROSS_COMPILER)gcc

GCC:=$(CROSS_COMPILER)g++

all:

$(CC) -o weather weather.c soapC.c soapClient.c stdsoap2.c

clean:

rm -f weather

    7 make , 執行程式

    如果一切正常的話會出現有關天氣的資訊。

    #./weather

    get weather ok !

    i(0), string((null))

    i(1), string(北京)

    i(2), string(晴)

    i(3), string(7 ~ -4 ℃)

    i(4), string(北風4-5級轉微風)

    i(5), string(今天)

    i(6), string(http://www.ayandy.com/images/晴.gif)

    i(7), string((null))

常見問題:

1 程式編繹通過,但是運作./weather是失敗,列印soap_call___ns3__getWeatherbyCityName failed

答:可能是你的linux主機的網絡有問題,試試ping 一下其它網絡位址http://www.ayandy.com是否成功。

如何失敗,則可能的原因有:一, 網絡沒有連接配接到公網 二  dns 沒有設定。

2 我運作./weather後出現的列印為亂碼,如下

get weather ok !

i(0), string((null))

i(1), string(?漪)

i(2), string(??

i(3), string(7 ~ -4 ??

i(4), string(??4-5蝥扯蓮敺桅?)

i(5), string(隞予)

i(6), string(http://www.ayandy.com/images/??gif)

i(7), string((null))

答:這種情況是編碼格式不正确,伺服器傳回的是utf-8的字元品, 是以要求你的終端的設定的編碼格式也為utf-8.

(pietty的設定方法,option->Encoding->Unicode utf-8)

3 修改makefile 交叉編繹無法通過,出現列印stdsoap2.c:(.text+0x1b04c): undefined reference to `isnan'的錯誤。

答:将stdsoap.h裡1067行 #  define soap_isnan(n) isnan(0) 修改為 #  define soap_isnan(n) (0)