• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            The power of C, the power of MD

            A problem is a chance to do your best
            posts - 11, comments - 22, trackbacks - 0, articles - 0
              C++博客 :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

            2010年9月6日

                 摘要: 上一節(jié)介紹了怎樣實現(xiàn)基本認證(Basic Authentication,以下簡稱basic方式),望文生義,也就是最簡單的用戶驗證方式,本節(jié)稍微深入一些,介紹用戶名令牌認證(Usernametoken Authentication,以下簡稱usernametoken方式)。  閱讀全文

            posted @ 2010-09-06 23:39 roy 閱讀(10912) | 評論 (0)編輯 收藏

            2010年9月4日

                 摘要:   閱讀全文

            posted @ 2010-09-04 18:51 roy 閱讀(6230) | 評論 (0)編輯 收藏

            2010年9月3日

            gSOAP 號稱是跨平臺的工具包,不過畢竟是屬于 g 字頭的,如果沒有了一系列 GNU 組件的支持,在其他類 Unix 系統(tǒng)編譯也會遇到不少困難。

             

            gSOAP README 說得也不是很清楚,只提到依賴于這些組件:

            1. Automake tools (make and GNU m4) to configure and build

            2. Bison http://www.gnu.org/software/bison or the alternative Yacc

            3. Flex http://flex.sourceforge.net

            4. OpenSSL (for optional HTTPS) http://www.openssl.org

            5. Zlib (for optional compression) http://www.zlib.net

            6. Pthreads or win32 threads (optional)

             

            實際上,我在 HP-UX 下編譯 gSOAP 的時候發(fā)現(xiàn),要成功編譯,還需要安裝 autoconf gawk make ,為解決中文亂碼問題,還需要安裝 libiconv 。雖然原系統(tǒng)就有 awk make ,但是由于版本問題,編譯時出錯。所以,建議大家編譯最新版的 gSOAP-2.7.17 時,按一下順序安裝組件:

            1.     autoconf-2.66 (http://ftp.gnu.org/gnu/autoconf/ )

            autoconf 是一個用于生成可以自動地配置軟件源代碼包以適應(yīng)多種 Unix 類系統(tǒng)的 shell 腳本的工具。

            2.     automake-1.10 (http://ftp.gnu.org/gnu/automake/ )

            automake 是一個從文件 Makefile.am 自動生成 Makefile.in 的工具。每個 Makefile.am 基本上是一系列 make 的宏定義( make 規(guī)則也會偶爾出現(xiàn))。生成的 Makefile.in 服從 GNU Makefile 標準。

            3.     m4-1.4.14 (http://ftp.gnu.org/gnu/m4/ )

            m4 是一個宏處理器。

            4.     gawk-3.1.8 (http://ftp.gnu.org/gnu/gawk/ )

            awk 地球人都知道。 HP-UX 自帶的 awk 不是 GNU 的,編譯 gSOAP 時執(zhí)行某些語句出錯,因此在編譯 gSOAP 時要使用 GNU 新版本。

            5.     make-3.81 (http://ftp.gnu.org/gnu/make/ )

            make 也是地球人都知道。 HP-UX 自帶的 make 編譯 gSOAP 時會出錯。

            6.     bison-2.4 (http://ftp.gnu.org/gnu/bison/ )

            語法分析生成器。

            7.     flex-2.5.35 (http://flex.sourceforge.net/ )

            詞法分析生成器。

            8.     zlib-1.2.5 (http://www.zlib.net/ )

            gzip LZW 壓縮庫。

            9.     libiconv-1.13.1 (http://ftp.gnu.org/pub/gnu/libiconv/ )

            字符編碼轉(zhuǎn)換工具,上一節(jié)有介紹。

             

            openssl 原來就已經(jīng)有,無需安裝。如果沒有或者版本很低,可以到這里下載: http://www.openssl.org/source/

             

            補充事項:

            1.     如何判斷某個組件是否需要安裝? 很簡單,到 LFS 官方網(wǎng)站參考用戶手冊: http://www.linuxfromscratch.org/lfs/view/stable/ ,查看一下該組件包含的 Installed program ,然后在命令行使用 which 命令找一下,如果找不到,可以肯定需要安裝

             

            2.     如何判斷某個組件是否需要升級? 如果通過上述方法能夠找到已安裝的組件,但是文件的時間比較久遠,而且不支持 —help 參數(shù)查看幫助信息或者 —version 參數(shù)查看版本信息,幾乎可以肯定需要升級,因為比較新的 GNU 程序一般都支持這些參數(shù)。如果通過 --version 顯示版本較低,也應(yīng)該升級

             

            3.     上述組件的安裝一般都是 ./configure && make && make install 三部曲。如果沒有 root 權(quán)限,可以使用 ./configure --prefix=/path/to/your/directory 指定合法的安裝路徑,然后根據(jù)需要指定 PATH SHLIB_PATH 環(huán)境變量。千萬要注意, HP-UX 的動態(tài)鏈接庫的環(huán)境變量是 SHLIB_PATH ,而不是和 Linux 下的 LD_LIBRARY_PATH

             

            4.     設(shè)置環(huán)境變量的時候也要注意,如果系統(tǒng)中已經(jīng)有舊版本的組件,并且新舊版本不在同一目錄, export 環(huán)境變量的時候要把新版本組件所在的 lib 目錄居前 ,這樣系統(tǒng)才能優(yōu)先搜索得到

             

            5.     HP-UX 下編譯 flex-2.5.35 時會遇到一個棘手的問題

            ld: Unsatisfied symbol "rpl_realloc" in file dfa.o

            1 errors.

            collect2: ld returned 1 exit status

             

            rpl_realloc 為關(guān)鍵字搜索,發(fā)現(xiàn)它出現(xiàn)在 configure 步驟產(chǎn)生的 config.h 當中

            /* Define to rpl_realloc if the replacement function should be used. */

            #define realloc rpl_realloc

             

            看樣子,可能是為了避免有些系統(tǒng)沒有 realloc ,而轉(zhuǎn)用 rpl_realloc 代替。這個 rpl_realloc 不知是哪個系統(tǒng)的函數(shù), HP-UX 應(yīng)該可以使用 realloc 這個標準 C 函數(shù)呀!于是,把這一行注釋了,重新 make 就正常了

             

            6.     gSOAP-2.7.17 的編譯指定要 automake-1.10 版本,如果像我那樣不慎安裝了 automake-1.11 ,需要自行在其 bin 目錄創(chuàng)建兩個鏈接,否則 gSOAP 就是傻到不認帳!

            aclocal-1.10 -> aclocal-1.11

            automake-1.10 -> automake-1.11

             

            7.     gSOAP 的傻事還不止一件,它只認 flex 的動態(tài)庫而不認靜態(tài)庫 ,偏偏 flex 只安裝了靜態(tài)庫。所以,安裝 flex 之后,需要手動編譯以生成 libfl.so ,然后再拷貝到其 lib 目錄。

            gcc -shared -fPCI -o libfl.so libmain.o libyywrap.o

            此外,還需要在其 lib 目錄創(chuàng)建兩個鏈接,其中第一個是 LFS 為保持 lex flex 的兼容性而建議的,至于第二個,完全是遷就 gSOAP 的壞脾氣

            libl.so -> libfl.so

            libl.so.1 -> libl.so

             

            如果上述準備工作全部完畢,那么即可正式編譯 gSOAP 。編譯步驟同樣是 ./configure && make && make install ,似乎乏善可陳。但是, gSOAP-2.7.17 似乎有一個 bug ,在 HP-UX 下編譯會報錯:

            stdsoap2_cpp.cpp: In function 'size_t frecv(soap*, char*, size_t)':

            stdsoap2_cpp.cpp:876: error: invalid conversion from 'socklen_t*' to 'int*'

            stdsoap2_cpp.cpp:876: error:   initializing argument 6 of 'int recvfrom(int, void*, int, int, void*, int*)'

            stdsoap2_cpp.cpp: In function 'int tcp_connect(soap*, const char*, const char*, int)':

            ……

             

            一大堆錯誤信息,其實是指向同一個錯誤: invalid conversion from 'socklen_t*' to 'int*'

             

            首先,使用 find 命令查找 stdsoap2_cpp.cpp 只有一個

            > find . -name "stdsoap2_cpp.cpp"

            ./gsoap/stdsoap2_cpp.cpp

             

            然后,根據(jù)錯誤信息,查看該源程序的 876 行附近,函數(shù)的第六個參數(shù),也就是最后一個參數(shù) k SOAP_SOCKLEN_T 類型的

             

            接著,查找所有的頭文件,看看該類型是哪個文件定義的

            > find . -name "*.h" | xargs grep -l SOAP_SOCKLEN_T

            ./gsoap/samples/calc_vs2005/calc_vs2005/stdsoap2.h

            ./gsoap/samples/wsse/stdsoap2.h

            ./gsoap/stdsoap2.h

            ./gsoap/VisualStudio2005/wsdl2h/wsdl2h/stdsoap2.h

             

            很明顯,就在 ./gsoap/stdsoap2.h 中。 Vi 之,在 709 行開始其定義:

               709  /* Portability: define SOAP_SOCKLEN_T */

               710  #if defined(_AIX)

               711  # if defined(_AIX43)

               712  #  define SOAP_SOCKLEN_T socklen_t

               713  # else

               714  #  define SOAP_SOCKLEN_T int

               715  # endif

               716  #elif defined(SOCKLEN_T)

               717  # define SOAP_SOCKLEN_T SOCKLEN_T

               718  #elif defined(__socklen_t_defined) || defined(_SOCKLEN_T) || defined(CYGWIN) || defined(FREEBSD) || defined(__FreeBSD__) || defined(OPENBSD) || define

            d(__QNX__) || defined(QNX) || defined(OS390) || defined(HP_UX)

               719  # define SOAP_SOCKLEN_T socklen_t

               720  #elif defined(IRIX) || defined(WIN32) || defined(__APPLE__) || defined(SUN_OS) || defined(OPENSERVER) || defined(TRU64) || defined(VXWORKS)

               721  # define SOAP_SOCKLEN_T int

               722  #else

               723  # define SOAP_SOCKLEN_T size_t

               724  #endif

             

            注意 718 719 行, gSOAP-2.7.17 HP-UX 下,把 SOAP_SOCKLEN_T 定義為 socklen_t ,而其它操作系統(tǒng)不是定義為 int 就定義為 size_t ,再聯(lián)系之前的錯誤信息 invalid conversion from 'socklen_t*' to 'int*' ,很清楚了,只要在 719 行把 socklen_t 改為 int 就肯定能夠在 HP-UX 下編譯通過了。或者嚴謹一些,把 718 行的 defined(HP_UX) 移到 720 行最后也可以。

             

            上面的問題解決了,繼續(xù)編譯工作,很可能會遇上另一個問題

            /usr/lib/hpux32/dld.so: Unsatisfied data symbol 'yylsp' in load module '/usr/lib/hpux32/libl.so.1'.

            /usr/lib/hpux32/dld.so: Unsatisfied data symbol 'yyolsp' in load module '/usr/lib/hpux32/libl.so.1'.

            /usr/lib/hpux32/dld.so: Unsatisfied data symbol 'yyfnd' in load module '/usr/lib/hpux32/libl.so.1'.

            ……

             

            這是由于系統(tǒng)原來就裝有 flex ,但不是最新版本,結(jié)果系統(tǒng)搜索到舊版本的 libl.so.1 而搜索不到新版本 libl.so.1 ,這就是為什么我在前面要特別強調(diào), export 環(huán)境變量的時候,要確保新版本所在的路徑在前面,并且要在 flex lib 目錄建立兩個鏈接的原因。

             

            按照上述步驟和錯誤處理方法,在 HP-UX 下編譯 gSOAP 應(yīng)該是不成問題的,推而廣之,在其它 Unix 下編譯 gSOAP 也應(yīng)該差不多。

             

            最后一個小問題是,在 HP-UX 下要使用剛剛編譯出來的 soapcpp2 生成存根程序,而不要使用前四節(jié)在 linux 目錄下的 soapcpp2

             

            > ../../src/soapcpp2 -C -L -x stock.h

             

            更進一步,如果在 HP-UX 下,需要用到 libxml2 解析 SOAP 響應(yīng)消息,除了編譯源代碼之外,也可以直接到下列網(wǎng)址下載基于 HP-UX 的二進制包:

            http://hpux.connect.org.uk/hppd/hpux/Gnome/libxml2-2.7.7/

             

            這個地址提供了幾種版本的二進制包,下載之前應(yīng)該在命令行輸入 uname –a 查看一下當前的操作系統(tǒng)信息:

            > uname -a

            HP-UX hostname B.11.23 U ia64 0850816723 unlimited-user license

             

            根據(jù)以上信息,應(yīng)當下載 Operating System HP-UX 11i v2(HP-UX 11.23) Architecture Itanium 2 的二進制包

             

            下載的包是 libxml2-2.7.7-ia64-11.23.depot.gz 。把它解壓后,有 root 權(quán)限的可以使用 HP-UX 專門的包管理工具安裝。沒有 root 權(quán)限也不要緊, depot 其實就是一個 tar 包,可以直接使用 tar 解包,把解包后的文件移動到合適的目錄,再設(shè)置好 PATH SHLIB_PATH 環(huán)境變量即可。

            http://blog.csdn.net/yui/archive/2010/08/09/5799465.aspx

            posted @ 2010-09-03 23:02 roy 閱讀(2580) | 評論 (1)編輯 收藏

            2010年8月30日

            電信provisioning系統(tǒng)中,常常需要與遠程服務(wù)器實時交換一些數(shù)據(jù),以完成用戶的請求。由于簡單對象訪問協(xié)議(Simple Object Access Protocol, SOAP)的流行,許多涉及到第三方的應(yīng)用,我們一般都比較樂意使用SOAP來開發(fā)。不過,由于可能涉及到公司的機密,本系列教程的開發(fā)實例盡量采用在網(wǎng)上已經(jīng)公開的Web Service資源。

             

            前面四節(jié)的教程,分別采用了股票信息和天氣預(yù)報的例子。而這兩個實例有一個共同點,SOAP響應(yīng)消息的數(shù)據(jù)結(jié)構(gòu)相對簡單,只需要按擬定的次序,事先約定返回數(shù)據(jù)代表的意義,就能夠?qū)崿F(xiàn)無歧義的溝通。這就使得gSOAP能夠以字符串數(shù)組的形式,定義返回結(jié)果,再加上一個整型變量,指示返回結(jié)果的個數(shù)。

             

            查看一下這兩個實例的soapStub.h,可以發(fā)現(xiàn),它們的結(jié)果集定義正是這樣的:

             

            struct ns1__ArrayOfString
            {
                    
            int __sizestring;       /* sequence of elements <string> */
                    
            char **string;  /* optional element of type xsd:string */
            };

             


            但是,如果服務(wù)端返回的是一個相對復(fù)雜的結(jié)果集,事情就不那么好辦了。例如,一個提供外匯匯率的Web Service,服務(wù)端會同時返回日元、瑞郎、英鎊、歐元、澳元、加元、港幣合計七種貨幣兌換美元的匯率情報,每種匯率情報又包括貨幣代碼、當前匯率、漲跌幅、買入價、賣出價、時間戳等多個子項。顯然,這不是一個線性結(jié)構(gòu),而是一個樹形結(jié)構(gòu),就不能使用ArrayOfString來表示了。

             

            這個案例的End point是:

            http://webservice.webxml.com.cn/WebServices/ExchangeRateWebService.asmx

            其WSDL是:

            http://webservice.webxml.com.cn/WebServices/ExchangeRateWebService.asmx?wsdl

             

            參考前面四節(jié)的內(nèi)容,快速建立其存根程序,不再累述。

             

            我們要實現(xiàn)的API是getExchangeRate,在soapStub.h中搜索,可以發(fā)現(xiàn)其返回結(jié)果集最終的定義是:

             

            struct _ns1__getExchangeRateResponse_getExchangeRateResult
            {
                    
            char *xsd__schema;      /* required element of type xsd:schema */
                    
            char *__any;
            };

             

            僅僅是兩個字符串!于是,最初版本的外匯匯率客戶端程序只能這樣寫:

            #include <iconv.h>

            #include 
            "soapH.h"
            #include 
            "ExchangeRateWebServiceSoap12.nsmap"

            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 type [end_point]\n", argv[0]);
                    printf(
            "\ttype = A : all rate\n");
                    printf(
            "\ttype = B : basic rate\n");
                    printf(
            "\ttype = C : cross rate\n");
                    exit(
            -1);
                }

                
            struct soap soap;
                soap_init(
            &soap);
                
            // don't set is OK
                
            //soap_set_mode(&soap, SOAP_C_UTFSTRING);

                
            struct _ns1__getExchangeRate request;
                
            struct _ns1__getExchangeRateResponse response;

                request.theType 
            = argv[1];
                
            char *endpoint = NULL;
                
            if ( argc == 3 )
                    endpoint 
            = argv[2];
                
            if ( soap_call___ns3__getExchangeRate(&soap, endpoint, NULL, &request, &response) == SOAP_OK ) {
                    printf(
            "%s\n", response.getExchangeRateResult->xsd__schema);
                    printf(
            "----------\n");
                    
            int ilen = strlen(response.getExchangeRateResult->__any);
                    
            int olen = ilen * 2;
                    
            char *output = (char *) malloc(sizeof(char* olen);
                    conv_charset(
            "GBK""UTF-8", response.getExchangeRateResult->__any, ilen, output, olen);
                    printf(
            "%s\n", output);
                    free(output);
                }
                
            else {
                    soap_print_fault(
            &soap, stderr);
                }

                soap_destroy(
            &soap);
                soap_end(
            &soap);
                soap_done(
            &soap);
                
            return 0;
            }

            其中,xsd__schema沒有中文字符,而__any含有中文字符,需要轉(zhuǎn)換成GBK編碼,具體可以參考前面兩節(jié)。

             

            編譯執(zhí)行,輸出結(jié)果如下圖:

             

             

             

            可以看出,服務(wù)端返回的兩個長字符串實際上都是基于XML形式的。gSOAP能夠自動幫我們完成的也就到此為止,剩下的需要我們自力更生了。

             

            不過,大家也不用頭疼,我們還有另外一個利器——libxml2!網(wǎng)上有很多關(guān)于libxml2的教程,所以我也不必多說,只要利用其中幾個函數(shù)和語句即可。

             

            1.     xmlParseMemory,字符串轉(zhuǎn)為XML文檔

            2.     xmlDocGetRootElement,獲取XML文檔根節(jié)點

            3.     xmlStrcmp,比較XML字符串,與strcmp差不多

            4.     curr = curr->xmlChildrenNode,XML節(jié)點指針指向第一個子節(jié)點

            5.     curr = curr->next,XML節(jié)點指針指向下一個兄弟節(jié)點

            6.     xmlNodeGetContent,獲取XML節(jié)點的內(nèi)容

            7.     xmlFreeDoc,釋放節(jié)點,與free差不多

             

            最終的外匯匯率客戶端程序如下:

             

            #include <iconv.h>
            #include 
            <libxml/parser.h>
            #include 
            <libxml/xmlmemory.h>

            #include 
            "soapH.h"
            #include 
            "ExchangeRateWebServiceSoap12.nsmap"

            #define FIELD_LEN 16

            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 type [end_point]\n", argv[0]);
                    printf(
            "\ttype = A : all rate\n");
                    printf(
            "\ttype = B : basic rate\n");
                    printf(
            "\ttype = C : cross rate\n");
                    exit(
            -1);
                }

                
            struct soap soap;
                soap_init(
            &soap);
                
            // don't set is OK
                
            //soap_set_mode(&soap, SOAP_C_UTFSTRING);

                
            struct _ns1__getExchangeRate request;
                
            struct _ns1__getExchangeRateResponse response;

                request.theType 
            = argv[1];
                
            char *endpoint = NULL;
                
            if ( argc == 3 )
                    endpoint 
            = argv[2];
                
            if ( soap_call___ns3__getExchangeRate(&soap, endpoint, NULL, &request, &response) == SOAP_OK ) {
                    
            int len = strlen(response.getExchangeRateResult->__any);
                    xmlDocPtr pdoc 
            = xmlParseMemory(response.getExchangeRateResult->__any, len);
                    xmlNodePtr root 
            = xmlDocGetRootElement(pdoc);
                    xmlNodePtr curr 
            = root;
                    
            while ( xmlStrcmp(curr->name, (const xmlChar *"getExchangeRate") )
                        curr 
            = curr->xmlChildrenNode;
                    
            for ( curr = curr->xmlChildrenNode; curr; curr = curr->next ) {
                        xmlNodePtr data;
                        
            for ( data = curr->xmlChildrenNode; data; data = data->next ) {
                            
            char ifield[FIELD_LEN];
                            
            char ofield[FIELD_LEN];
                            strcpy(ifield, xmlNodeGetContent(data));
                            
            if ( conv_charset("GBK""UTF-8", ifield, strlen(ifield), ofield, FIELD_LEN) )
                                printf(
            "%s\t%s\n", data->name, ifield);
                            
            else
                                printf(
            "%s\t%s\n", data->name, ofield);
                        }
                        printf(
            "\n");
                    }
                    xmlFreeDoc(pdoc);
                }
                
            else {
                    soap_print_fault(
            &soap, stderr);
                }

                soap_destroy(
            &soap);
                soap_end(
            &soap);
                soap_done(
            &soap);
                
            return 0;
            }

             


            編譯時,需要鏈接libxml2庫,同時指定頭文件所在路徑:

            gcc -O2 -o exchange exchange.c soapC.c soapClient.c ../../stdsoap2.c -I../.. -I/usr/include/libxml2 -L../.. -lgsoap -lxml2

             

            執(zhí)行結(jié)果(部分)如下:

             

            -bash-3.2$ ./exchange B

            Code    JPY

            Currency        日元

            ClosePrice      87.08

            DiffPercent     -0.29%

            DiffAmount      -0.25

            OpenPrice       87.5

            HighPrice       87.71

            LowPrice        87.04

            Range   0.77%

            BuyPrice        87.08

            SellPrice       87.12

            ChangeColor     Green

            DataTime        16:57:54

             

            Code

            CHF

            Currency        瑞郎

            ClosePrice      1.0552

            DiffPercent     0.16%

            DiffAmount      0.0017

            OpenPrice       1.054

            HighPrice       1.0552

            LowPrice        1.0498

            Range   0.51%

            BuyPrice        1.0552

            SellPrice       1.0556

            ChangeColor     Red

            DataTime        16:57:52


            http://blog.csdn.net/yui/archive/2010/07/26/5767494.aspx

            posted @ 2010-08-30 17:12 roy 閱讀(3780) | 評論 (0)編輯 收藏

            2010年8月22日

            電信provisioning系統(tǒng)中,常常需要與遠程服務(wù)器實時交換一些數(shù)據(jù),以完成用戶的請求。由于簡單對象訪問協(xié)議(Simple Object Access Protocol, SOAP)的流行,許多涉及到第三方的應(yīng)用,我們一般都比較樂意使用SOAP來開發(fā)。不過,由于可能涉及到公司的機密,本系列教程的開發(fā)實例盡量采用在網(wǎng)上已經(jīng)公開的Web Service資源。
             
            上一節(jié),講解了用iconv解決gSOAP輸出的中文文本亂碼的問題。在本節(jié)中,我們用一個天氣預(yù)報客戶端的例子,簡述一下gSOAP輸入的中文文本亂碼的問題。
             
            Webxml.com.cn提供的天氣預(yù)報web服務(wù),endpoint地址是:http://webservice.webxml.com.cn/WebServices/WeatherWebService.asmx,大家可以點擊進去,查看一下該服務(wù)的所有對外提供的接口。其中,利用getWeatherbyCityName接口,可以按給定的城市名字查詢該城市的天氣預(yù)報,如果輸入的城市名字不能識別,將統(tǒng)一返回北京的天氣預(yù)報。
             
            根據(jù)前三節(jié)的內(nèi)容,我們可以很快地準備好其客戶端存根程序:
            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
             
            由于程序并不復(fù)雜,直接給出其源代碼:
            #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

             

            基本上與上一節(jié)的股票信息客戶端差不多,唯一不同的是,作為輸入?yún)?shù)的城市名字,首先需要iconv轉(zhuǎn)換編碼,從GBK轉(zhuǎn)到UTF-8,才可以提交給服務(wù)端。各位可以試一下,不作轉(zhuǎn)換的話,無論輸入什么,服務(wù)端只會返回北京的天氣預(yù)報,因為傳入的參數(shù)在服務(wù)端產(chǎn)生了亂碼。

             

            以下為正常的執(zhí)行結(jié)果,輸入廣州,可以得到廣州的天氣預(yù)報:


            如上圖,最后一段的介紹也出現(xiàn)了亂碼,不過我認為這是putty的問題,行末的最后一個全角字符,如果只能顯示一半的話,下一行開始將產(chǎn)生亂碼,如果再遇到一個半角字符,又能顯示正常了。

            http://blog.csdn.net/yui/archive/2010/07/23/5758906.aspx

            posted @ 2010-08-22 18:04 roy 閱讀(2182) | 評論 (0)編輯 收藏

            2010年8月17日

            電信provisioning系統(tǒng)中,常常需要與遠程服務(wù)器實時交換一些數(shù)據(jù),以完成用戶的請求。由于簡單對象訪問協(xié)議(Simple Object Access Protocol, SOAP)的流行,許多涉及到第三方的應(yīng)用,我們一般都比較樂意使用SOAP來開發(fā)。不過,由于可能涉及到公司的機密,本系列教程的開發(fā)實例盡量采用在網(wǎng)上已經(jīng)公開的Web Service資源。
             
            我開發(fā)SOAP應(yīng)用程序已經(jīng)有一定的經(jīng)驗,在C/C++環(huán)境下一般使用gSOAP,而在Java環(huán)境下一般采用axis2。比較兩者的話,除了開發(fā)語言之外,還是有不少差別,處理中文字符就是其中之一。網(wǎng)上分別搜索一下“axis2 亂碼”和“gSOAP 亂碼”,匹配的結(jié)果是相差很遠的。Axis2好像比較智能,能夠識別服務(wù)端的字符編碼,這方面的問題也少,而最新版本的gSOAP,很可能還是需要程序員做多很多功夫。
             
            在第一節(jié)客戶端的教程中,輸出的中文股票名稱,其實就是亂碼,不過為了主次之分,當時做了特別處理,忽略過去。
             
            網(wǎng)上解決gSOAP亂碼的主流方案是,初始化soap對象之后對其設(shè)置SOAP_C_UTFSTRING參數(shù),例如:
                    struct soap soap;
                    soap_init(&soap);
                    soap_set_mode(&soap, SOAP_C_UTFSTRING);
             
            但是,單純這樣修改,在某些特定設(shè)置的機器上可能有效,反正我試過,仍然是亂碼,如下圖。怎么辦呢?
             
             
            Linux下有一個字符編碼轉(zhuǎn)換的工具iconv,同時也提供了一套可編程的接口。利用它,就可以測試出來自于服務(wù)端中文字符編碼的類型,從而進一步實現(xiàn)在程序中自動轉(zhuǎn)換編碼。
             
            Iconv常用用法是:iconv -t=to_charset -f=from_charset filename
            因此,把需要轉(zhuǎn)換編碼的內(nèi)容保存為一個文件,然后執(zhí)行iconv試出需要轉(zhuǎn)換的編碼類型。from­_charset幾乎百分百肯定就是utf8,那么to_charset來來去去就那么幾個,一個個試也很快試出來了。最終得出的結(jié)果是gbk編碼,從而修改客戶端程序以解決亂碼問題。

            #include <iconv.h>

            #include 
            "soapH.h"
            #include 
            "ChinaStockWebServiceSoap12.nsmap"

            #define OUTPUT_LEN 32

            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 stock_code [end_point]\n", argv[0]);
                    exit(
            -1);
                }

                
            struct soap soap;
                soap_init(
            &soap);
                soap_set_mode(
            &soap, SOAP_C_UTFSTRING);

                
            struct _ns1__getStockInfoByCode request;
                
            struct _ns1__getStockInfoByCodeResponse response;

                request.theStockCode 
            = argv[1];
                
            char *endpoint = NULL;
                
            if ( argc == 3 )
                    endpoint 
            = argv[2];
                
            if ( soap_call___ns3__getStockInfoByCode(&soap, endpoint, NULL, &request, &response) == SOAP_OK ) {
                    
            int element_counter = response.getStockInfoByCodeResult->__sizestring;
                    
            int i = 0;
                    
            for ( i = 0; i < element_counter; i++ ) {
                        
            switch ( i ) {
                            
            case 0  : printf("Stock code        : "); break;
                            
            case 1  : printf("Stock name        : "); break;
                            
            case 2  : printf("Timestamp         : "); break;
                            
            case 3  : printf("Latest price      : "); break;
                            
            case 4  : printf("Closing price T-1 : "); break;
                            
            case 5  : printf("Opening price     : "); break;
                            
            case 6  : printf("Ups and downs     : "); break;
                            
            case 7  : printf("Mininum price     : "); break;
                            
            case 8  : printf("Maxinum price     : "); break;
                            
            case 9  : printf("Amount of up/down : "); break;
                            
            case 10 : printf("Trading volume    : "); break;
                            
            case 11 : printf("Trading amount    : "); break;
                            
            case 12 : printf("Buy price         : "); break;
                            
            case 13 : printf("Sell price        : "); break;
                            
            case 14 : printf("Agency trans      : "); break;
                            
            case 15 : printf("Buy  1            : "); break;
                            
            case 16 : printf("Buy  2            : "); break;
                            
            case 17 : printf("Buy  3            : "); break;
                            
            case 18 : printf("Buy  4            : "); break;
                            
            case 19 : printf("Buy  5            : "); break;
                            
            case 20 : printf("Sell 1            : "); break;
                            
            case 21 : printf("Sell 2            : "); break;
                            
            case 22 : printf("Sell 3            : "); break;
                            
            case 23 : printf("Sell 4            : "); break;
                            
            case 24 : printf("Sell 5            : "); break;
                            
            default : break;
                        }
                        
            //printf("%s\n", response.getStockInfoByCodeResult->string[i]);
                        size_t ilen = strlen(response.getStockInfoByCodeResult->string[i]);
                        
            char output[OUTPUT_LEN];
                        
            if ( conv_charset("GBK""UTF-8", response.getStockInfoByCodeResult->string[i], ilen, output, OUTPUT_LEN) )
                            printf(
            "%s\n", response.getStockInfoByCodeResult->string[i]);
                        
            else
                            printf(
            "%s\n", output);
                    }
                }
                
            else {
                    soap_print_fault(
            &soap, stderr);
                }

                soap_destroy(
            &soap);
                soap_end(
            &soap);
                soap_done(
            &soap);
                
            return 0;
            }

            測試成功,如下圖:
             


            http://blog.csdn.net/yui/archive/2010/07/21/5753879.aspx

            posted @ 2010-08-17 12:01 roy 閱讀(2903) | 評論 (5)編輯 收藏

            2010年8月14日

                 摘要: 電信provisioning系統(tǒng)中,常常需要與遠程服務(wù)器實時交換一些數(shù)據(jù),以完成用戶的請求。由于簡單對象訪問協(xié)議(Simple Object Access Protocol, SOAP)的流行,許多涉及到第三方的應(yīng)用,我們一般都比較樂意使用SOAP來開發(fā)。不過,由于可能涉及到公司的機密,本系列教程的開發(fā)實例盡量采用在網(wǎng)上已經(jīng)公開的Web Service資源。 上文已經(jīng)交待了gSOAP在L...  閱讀全文

            posted @ 2010-08-14 23:46 roy 閱讀(2259) | 評論 (0)編輯 收藏

            2010年8月2日

            電信provisioning系統(tǒng)中,常常需要與遠程服務(wù)器實時交換一些數(shù)據(jù),以完成用戶的請求。由于簡單對象訪問協(xié)議(Simple Object Access Protocol, SOAP)的流行,許多涉及到第三方的應(yīng)用,我們一般都比較樂意使用SOAP來開發(fā)。不過,由于可能涉及到公司的機密,本系列教程的開發(fā)實例盡量采用在網(wǎng)上已經(jīng)公開的Web Service資源。
             
            gSOAP是一套開源的C/C++軟件工具包,使用它能夠很方便地開發(fā)SOAP網(wǎng)頁服務(wù)和基于XML的應(yīng)用程序,就像JAVA里面的axis。
             
            首先,我們需要從以下地址下載最新版本的gSOAP 2.7.17:
            https://sourceforge.net/projects/gsoap2/files/
             
            其次,gSOAP依賴于Bison和Flex,編譯gSOAP的時候會用到,如果沒有,從這里下載:
            Bison:http://www.gnu.org/software/bison/
            Flex:http://flex.sourceforge.net/
             
            關(guān)于這兩個工具包的安裝步驟可以參考最新的LFS手冊:
            http://www.linuxfromscratch.org/lfs/view/6.4/chapter06/bison.html
            http://www.linuxfromscratch.org/lfs/view/6.4/chapter06/flex.html
             
            如果不是root用戶,沒有安裝權(quán)限的話,可以在configure的時候使用--prefix=/path/to/your/own/directory,指定安裝路徑。裝好之后,修改用戶目錄的.profile文件,更改PATH和LD_LIBRARY_PATH環(huán)境變量,使得系統(tǒng)能夠正確搜索到你安裝后的可執(zhí)行文件和庫文件即可。
             
            這兩步準備工作完成后,我們就可以開始編譯gSOAP。Linux下編譯安裝源代碼包無非就是tar zxvf xxx,configure,make,make install,由于我不是root用戶,沒有安裝的權(quán)限,那么不執(zhí)行make install也可以使用gSOAP開發(fā)程序,只不過使用的時候常常需要指定路徑。
             
            現(xiàn)在我們的目標是開發(fā)一個獲取股票信息的客戶端程序。服務(wù)端采用webxml開發(fā)的WSDL,其URL是:http://webservice.webxml.com.cn/WebServices/ChinaStockWebService.asmx?wsdl
             
            首先,在gsoap-2.7/gsoap/wsdl/下創(chuàng)建一個stock目錄
            -bash-3.2$ mkdir -p stock
             
            改變當前路徑為stock
            -bash-3.2$ cd stock
             
            使用wsdl2h生成stock.h,如果希望生成純C代碼,需要加上-c參數(shù),否則,將會生成C++代碼
            -bash-3.2$ ../wsdl2h -c -o stock.h http://webservice.webxml.com.cn/WebServices/ChinaStockWebService.asmx?wsdl
             
            **  The gSOAP WSDL/Schema processor for C and C++, wsdl2h release 1.2.17
            **  Copyright (C) 2000-2010 Robert van Engelen, Genivia Inc.
            **  All Rights Reserved. This product is provided "as is", without any warranty.
            **  The wsdl2h tool is released under one of the following two licenses:
            **  GPL or the commercial license by Genivia Inc. Use option -l for more info.
             
            Saving stock.h
             
            Cannot open file 'typemap.dat'
            Problem reading type map file 'typemap.dat'.
            Using internal type definitions for C instead.
             
             
            Connecting to 'http://webservice.webxml.com.cn/WebServices/ChinaStockWebService.asmx?wsdl' to retrieve WSDL/XSD...
            Connected, receiving...
            Done reading 'http://webservice.webxml.com.cn/WebServices/ChinaStockWebService.asmx?wsdl'
             
            To complete the process, compile with:
            > soapcpp2 stock.h
             
            然后,使用soapcpp2生成客戶端存根程序和相關(guān)的頭文件、資源文件,由于我們只開發(fā)客戶端程序,所以可以指定-C參數(shù)
            -bash-3.2$ ../../bin/linux386/soapcpp2 -C stock.h
             
            **  The gSOAP code generator for C and C++, soapcpp2 release 2.7.17
            **  Copyright (C) 2000-2010, Robert van Engelen, Genivia Inc.
            **  All Rights Reserved. This product is provided "as is", without any warranty.
            **  The soapcpp2 tool is released under one of the following three licenses:
            **  GPL, the gSOAP public license, or the commercial license by Genivia Inc.
             
            Saving soapStub.h annotated copy of the input declarations
            Saving soapH.h interface declarations
            Saving soapC.c XML serializers
            Saving soapClient.c client calling stubs
            Saving soapClientLib.c client stubs with serializers (use only for libs)
            Using ns2 service name: ChinaStockWebServiceSoap
            Using ns2 service style: document
            Using ns2 service encoding: literal
            Using ns2 service location: http://webservice.webxml.com.cn/WebServices/ChinaStockWebService.asmx
            Using ns2 schema namespace: http://WebXml.com.cn/ChinaStockWebServiceSoap
            Saving ChinaStockWebServiceSoap.getStockImageByCode.req.xml sample SOAP/XML request
            Saving ChinaStockWebServiceSoap.getStockImageByCode.res.xml sample SOAP/XML response
            Saving ChinaStockWebServiceSoap.getStockImageByteByCode.req.xml sample SOAP/XML request
            Saving ChinaStockWebServiceSoap.getStockImageByteByCode.res.xml sample SOAP/XML response
            Saving ChinaStockWebServiceSoap.getStockImage_kByCode.req.xml sample SOAP/XML request
            Saving ChinaStockWebServiceSoap.getStockImage_kByCode.res.xml sample SOAP/XML response
            Saving ChinaStockWebServiceSoap.getStockImage_kByteByCode.req.xml sample SOAP/XML request
            Saving ChinaStockWebServiceSoap.getStockImage_kByteByCode.res.xml sample SOAP/XML response
            Saving ChinaStockWebServiceSoap.getStockInfoByCode.req.xml sample SOAP/XML request
            Saving ChinaStockWebServiceSoap.getStockInfoByCode.res.xml sample SOAP/XML response
            Saving ChinaStockWebServiceSoap.nsmap namespace mapping table
            Using ns3 service name: ChinaStockWebServiceSoap12
            Using ns3 service style: document
            Using ns3 service encoding: literal
            Using ns3 service location: http://webservice.webxml.com.cn/WebServices/ChinaStockWebService.asmx
            Using ns3 schema namespace: http://WebXml.com.cn/ChinaStockWebServiceSoap12
            Saving ChinaStockWebServiceSoap12.getStockImageByCode.req.xml sample SOAP/XML request
            Saving ChinaStockWebServiceSoap12.getStockImageByCode.res.xml sample SOAP/XML response
            Saving ChinaStockWebServiceSoap12.getStockImageByteByCode.req.xml sample SOAP/XML request
            Saving ChinaStockWebServiceSoap12.getStockImageByteByCode.res.xml sample SOAP/XML response
            Saving ChinaStockWebServiceSoap12.getStockImage_kByCode.req.xml sample SOAP/XML request
            Saving ChinaStockWebServiceSoap12.getStockImage_kByCode.res.xml sample SOAP/XML response
            Saving ChinaStockWebServiceSoap12.getStockImage_kByteByCode.req.xml sample SOAP/XML request
            Saving ChinaStockWebServiceSoap12.getStockImage_kByteByCode.res.xml sample SOAP/XML response
            Saving ChinaStockWebServiceSoap12.getStockInfoByCode.req.xml sample SOAP/XML request
            Saving ChinaStockWebServiceSoap12.getStockInfoByCode.res.xml sample SOAP/XML response
            Saving ChinaStockWebServiceSoap12.nsmap namespace mapping table
             
            Compilation successful
             
            接著,就可以利用存根程序提供的接口編寫客戶端程序了,過程相當簡單。
            #include "soapH.h"
            #include 
            "ChinaStockWebServiceSoap12.nsmap"

            int main(int argc, char **argv) {
                    
            if ( argc != 2 ) {
                            printf(
            "Usage: %s stock_code\n", argv[0]);
                            exit(
            -1);
                    }

                    
            struct soap soap;
                    soap_init(
            &soap);
                    
            struct _ns1__getStockInfoByCode request;
                    
            struct _ns1__getStockInfoByCodeResponse response;

                    request.theStockCode 
            = argv[1];
                    
            if ( soap_call___ns3__getStockInfoByCode(&soap, NULL, NULL, &request, &response) == SOAP_OK ) {
                            
            int element_counter = response.getStockInfoByCodeResult->__sizestring;
                            
            int i = 0;
                            
            for ( i = 0; i < element_counter; i++ ) {
                                    
            switch ( i ) {
                                            
            case 0  : printf("Stock code        : "); break;
                                            
            case 1  : printf("Stock name        : "); break;
                                            
            case 2  : printf("Timestamp         : "); break;
                                            
            case 3  : printf("Latest price      : "); break;
                                            
            case 4  : printf("Closing price T-1 : "); break;
                                            
            case 5  : printf("Opening price     : "); break;
                                            
            case 6  : printf("Ups and downs     : "); break;
                                            
            case 7  : printf("Mininum price     : "); break;
                                            
            case 8  : printf("Maxinum price     : "); break;
                                            
            case 9  : printf("Amount of up/down : "); break;
                                            
            case 10 : printf("Trading volume    : "); break;
                                            
            case 11 : printf("Trading amount    : "); break;
                                            
            case 12 : printf("Buy price         : "); break;
                                            
            case 13 : printf("Sell price        : "); break;
                                            
            case 14 : printf("Agency trans      : "); break;
                                            
            case 15 : printf("Buy  1            : "); break;
                                            
            case 16 : printf("Buy  2            : "); break;
                                            
            case 17 : printf("Buy  3            : "); break;
                                            
            case 18 : printf("Buy  4            : "); break;
                                            
            case 19 : printf("Buy  5            : "); break;
                                            
            case 20 : printf("Sell 1            : "); break;
                                            
            case 21 : printf("Sell 2            : "); break;
                                            
            case 22 : printf("Sell 3            : "); break;
                                            
            case 23 : printf("Sell 4            : "); break;
                                            
            case 24 : printf("Sell 5            : "); break;
                                            
            default : break;
                                    }
                                    printf(
            "%s\n", response.getStockInfoByCodeResult->string[i]);
                            }
                    }
                    
            else {
                            soap_print_fault(
            &soap, stderr);
                    }

                    soap_destroy(
            &soap);
                    soap_end(
            &soap);
                    soap_done(
            &soap);
                    
            return 0;
            }

            基本上都是套用差不多的格式,不清楚具體參數(shù)意義的話,可以參考soapcpp2生成的存根程序及其頭文件。把上述代碼保存為stock.c,編譯命令是:
            gcc -O2 -o stock stock.c soapC.c soapClient.c ../../stdsoap2.c -I../.. -L../.. –lgsoap
             
            可以看到,編譯時,除了stock.c,還需要包括存根程序soapC.c和soapClient.c,以及gSOAP運行時引擎stdsoap2.c,另外還需要指定頭文件搜索路徑、庫文件搜索路徑,以及告訴編譯器,鏈接libgsoap
             
            一切正常的話,就大功告成了:
            -bash-3.2$ ./stock sh600000
            Stock code        : sh600000
            Stock name        : 浦發(fā)銀行
            Timestamp         : 2010-07-08 15:02:07
            Latest price      : 13.79
            Closing price T-1 : 13.76
            Opening price     : 13.88
            Ups and downs     : 0.03
            Mininum price     : 13.73
            Maxinum price     : 14.06
            Amount of up/down : 0.22%
            Trading volume    : 451017.84
            Trading amount    : 62602.5809
            Buy price         : 13.78
            Sell price        : 13.79
            Agency trans      : 34.07%
            Buy  1            : 13.78 / 1622.88
            Buy  2            : 13.77 / 687.10
            Buy  3            : 13.76 / 785.00
            Buy  4            : 13.75 / 1430.00
            Buy  5            : 13.74 / 264.00
            Sell 1            : 13.79 / 33.70
            Sell 2            : 13.80 / 64.17
            Sell 3            : 13.81 / 290.80
            Sell 4            : 13.82 / 1318.70
            Sell 5            : 13.83 / 647.70

             

            http://blog.csdn.net/yui/archive/2010/07/08/5721877.aspx

            posted @ 2010-08-02 17:43 roy 閱讀(3399) | 評論 (6)編輯 收藏

            2010年7月30日

            libz提供了一套與gzip有關(guān)的API,libbz2提供了一套與bzip2有關(guān)的API。我們可以利用其中幾個常用的函數(shù),在自己的項目中實現(xiàn)壓縮、解壓縮功能。這兩個庫文件一般在linux系統(tǒng)中都會有,如果沒有,可以分別到以下網(wǎng)址下載其源代碼:

             

            gzip: http://www.gzip.org/

            bzip2: http://www.bzip.org/index.html

             

            libz最有用的函數(shù)有四個:

             

            gzFile gzopen(const char *path, const char *mode);

            int gzclose(gzFile file);

            int gzread(gzFile file, void *buf, unsigned len);

            int gzwrite(gzFile file, const void *buf, unsigned len);

             

            追蹤其源代碼的話,可以發(fā)現(xiàn),gzFile也就是void *

             

            libbz2最有用的函數(shù)也有四個:

             

            BZFILE *BZ2_bzopen(const char *path, const char *mode);

            void BZ2_bzclose(BZFILE *file);

            int BZ2_bzread(BZFILE *file, void *buf, int len);

            int BZ2_bzwrite(BZFILE *file, void *buf, int len);

             

            追蹤其源代碼的話,可以發(fā)現(xiàn),BZFILE也就是void

             

            所以說,libz的四個函數(shù)與libbz2的四個函數(shù),無論從名字上看,還是從參數(shù)上看,都是如出一轍的。只不過,gzopen()和gzread()可以打開和讀取任何文件,而BZ2_bzopen()和BZ2_bzread()只能打開和讀取bzip2壓縮的文件。

             

            事實上,它們與普通文件的打開、關(guān)閉、讀取、寫入的四個函數(shù),基本上是對應(yīng)的:

             

            FILE *fopen(const char *path, const char *mode);

            int fclose(FILE *fp);

            int fread(void *buf, int size_of_element, int len, FILE *fp);

            int fwrite(void *buf, int size_of_element, int len, FILE *fp);

             

            要打開一個打算讀取的二進制文件,三個打開函數(shù)的調(diào)用分別是:

            gzopen("filename", "r");

            BZ2_bzopen("filename", "r");

            fopen("filename", "rb");

             

            要打開一個打算寫入的二進制文件,三個打開函數(shù)的調(diào)用分別是:

            gzopen("filename", "w");

            BZ2_bzopen("filename", "w");

            fopen("filename", "w");

             

            可以說參數(shù)的使用是基本一樣的,不過gzopen()和BZ2_bzopen()的mode參數(shù)一般沒有"rb"而只有"r",因為它們處理的基本上都是二進制文件,不需要特別指明。此外,mode參數(shù)還有其它用法,比如制定壓縮率等,具體可以查看源代碼。

             

            不同的地方之一,F(xiàn)ILE是一個關(guān)于文件信息的結(jié)構(gòu)體,而不是void類型,之二,gzread()、gzwrite()、BZ2_bzread()和BZ2_bzwrite()的參數(shù)位置與fread()和fwrite()不一樣,同時也省略了size_of_element參數(shù)。

             

            有了這兩套API,我們就可以很方便地寫出程序?qū)ξ募M行壓縮、解壓縮操作,更多的是,把壓縮、解壓縮功能集成到自己的項目中去,使得項目支持壓縮格式。舉例如下:

             

            1. 如果使用libz的API,壓縮就是對源文件進行fopen()/fread()/fclose()操作,對目標文件進行g(shù)zopen()/gzwrite()/gzclose()操作;解壓縮就是對源文件進行g(shù)zopen()/gzread()/gzclose()操作,對目標文件進行fopen()/fwrite()/fclose()操作
            2. 如果使用libbz2的API,壓縮就是對源文件進行fopen()/fread()/fclose()操作,對目標文件進行BZ2_bzopen()/BZ2_bzwrite()/BZ2_bzclose()操作;解壓縮就是對源文件進行BZ2_bzopen()/BZ2_bzread()/BZ2_bzclose()操作,對目標文件進行fopen()/fwrite()/fclose()操作

             

            如果要直接使用libz和libbz2,很簡單,只需要做到三件事:

            1.     include頭文件。把zlib.h和bzlib.h包含到項目源程序中

            2.     鏈接庫文件。如果由于權(quán)限問題不能安裝庫文件,需要在編譯時指定庫文件的路徑

            3.     如果庫文件沒有安裝在系統(tǒng)默認的搜索路徑,運行前還要修改LD_LIBRARY_PATH環(huán)境變量,使得運行時能夠找到庫文件

             

            值得注意的是,以上列出的只是libz和libbz2里面最常用、比較高級的函數(shù),其實,這兩個庫文件里還有其它底層的函數(shù),利用這些底層函數(shù),甚至可以解壓.Z結(jié)尾的壓縮文件。具體做法就要慢慢參透libz的全部源代碼了。

             

            本文來自CSDN博客,轉(zhuǎn)載請標明出處:http://blog.csdn.net/yui/archive/2010/07/01/5707842.aspx

            posted @ 2010-07-30 12:22 roy 閱讀(3002) | 評論 (0)編輯 收藏

            2010年7月29日

                 摘要: 眾所周知,C程序的主函數(shù)有兩個參數(shù),其中,第一個參數(shù)是整型,可以獲得包括程序名字的參數(shù)個數(shù),第二個參數(shù)是字符數(shù)組指針或字符指針的指針,可以按順序獲得命令行上各個字符串參數(shù)。其原形是: int main(int argc, char *argv[]); 或者 int main(int argc, char **argv);   如果有一個解析CDR的程序,名叫destroy,負責...  閱讀全文

            posted @ 2010-07-29 18:01 roy 閱讀(2145) | 評論 (0)編輯 收藏

            亚洲国产精品成人久久蜜臀| 国内精品伊人久久久久av一坑 | 日本久久久久久久久久| 久久精品国产色蜜蜜麻豆| 理论片午午伦夜理片久久| 一本色道久久综合狠狠躁| 久久人爽人人爽人人片AV| 99久久无色码中文字幕| 久久天天躁狠狠躁夜夜2020| 久久久久久久久久久久久久| 97精品国产91久久久久久| 久久久久亚洲AV成人网人人网站| 中文字幕无码久久人妻| 久久天堂AV综合合色蜜桃网| 久久激情亚洲精品无码?V| 人人狠狠综合久久88成人| 国产精品成人久久久久三级午夜电影| 亚洲精品无码久久久久AV麻豆| 久久99国产精品尤物| 久久国产精品免费| 国产午夜福利精品久久2021| 开心久久婷婷综合中文字幕| 97超级碰碰碰久久久久| 亚洲欧美一区二区三区久久| 久久久久国产一级毛片高清版| 亚洲精品无码专区久久同性男| 久久精品国产免费一区| 久久99热这里只有精品国产| 国产毛片久久久久久国产毛片| 亚洲精品午夜国产VA久久成人| 久久精品中文字幕第23页| 久久99国产精品久久99| 亚洲AV日韩精品久久久久久| 午夜视频久久久久一区 | 久久久久久久精品妇女99| 国产A级毛片久久久精品毛片| 久久人人爽爽爽人久久久| 精品综合久久久久久98| 日本加勒比久久精品| 久久久久国产日韩精品网站| 欧美日韩中文字幕久久伊人|