狂奔 lion

          自強不息

          淺談Java中的通信機制及與C/C++ API的集成(下)

          接著上次的話題,今天我們聊聊gSOAP這個框架,我們把用C寫的舊有系統(tǒng)用gSOAP改造一下,通過SOA的形式發(fā)布出去。
          上文提到,利用gSOAP可以做到以下3點:
          1 一個Stand-alone的服務(wù)器外殼
          2 一個根據(jù)API程序自動生成的Web Services服務(wù)
          3 一個WSDL描述符文件

          客戶根據(jù) WSDL 描述文檔,會生成一個 SOAP 請求消息。Web Services 都是放在Web服務(wù)器后面,客戶生成的SOAP請求會被嵌入在一個HTTP POST請求中,發(fā)送到 Web 服務(wù)器來。Web 服務(wù)器再把這些請求轉(zhuǎn)發(fā)給 Web Services 請求處理器。請求處理器的作用在于,解析收到的 SOAP 請求,調(diào)用 Web Services,然后再生成相應(yīng)的 SOAP 應(yīng)答。Web 服務(wù)器得到 SOAP 應(yīng)答后,會再通過 HTTP應(yīng)答的方式把信息送回到客戶端。
          WSDL是Web服務(wù)中客戶端和服務(wù)端溝通的橋梁,描述了對象提供的方法。SOAP幫我們制定了一份被官方認可的對象的封裝方法。有了WSDL,客戶端只關(guān)心如何把參數(shù)用Soap封裝起來發(fā)出去,并獲取結(jié)果。服務(wù)端只關(guān)心如何對Soap進行拆包->服務(wù)->封包。gSOAP可以幫我們實現(xiàn)上述過程中的拆包和封包,而我們可以只關(guān)心服務(wù)的實現(xiàn)。

          言歸正傳,在這里我們以一個簡單的實現(xiàn)加、減、開放的Web Services的服務(wù)為例子,介紹gSOAP的使用:
          為了發(fā)布這個Web服務(wù),首先我們需要把服務(wù)的接口定義好,這個服務(wù)可能是一個現(xiàn)有服務(wù)的Adapter,為此我們定義頭文件
          calc.h:
          typedef double xsd__double;
          int ns__add(xsd__double a, xsd__double b, xsd__double &result);
          int ns__sub(xsd__double a, xsd__double b, xsd__double &result);
          int ns__sqrt(xsd__double a, xsd__double &result); 
          注意到這里面我們把double定義成了xsd__double(兩個下劃線),這是為了告訴gSOAP,我們需要的soap格式和WSDL格式是基于Document/literal的而非rpc/encoded.為了不把事情搞復(fù)雜,在這里我只能說,Java1.6自帶的Web Services工具只支持Document/literal格式的WSDL,所以我們生成這種格式的WSDL。至于這兩種格式之間選擇和他們的long story,大家可以參考下面的文章:
          http://www.ibm.com/developerworks/webservices/library/ws-whichwsdl/
          編寫好頭文件后,我們就可以利用gSOAP提供的工具進行生成了:
          /usr/lib/gsoap-2.7/bin/soapcpp2 -S -2 calc.h
          生成的主要文件詳見附件。
          下面我們實現(xiàn)calc.h中定義的函數(shù):
          // Contents of file "calc.cpp": 
          #include "soapH.h" 
          #include 
          "ns.nsmap" 
          #include 
          <math.h> 
          int main()
          {
             struct soap soap;
             
          int m, s; // master and slave sockets
             soap_init(&soap);
             m 
          = soap_bind(&soap, "localhost"9999100);
             
          if (m < 0)
                soap_print_fault(
          &soap, stderr);
             
          else
             {
                fprintf(stderr, 
          "Socket connection successful: master socket = %d\n", m);
                
          for (int i = 1; ; i++)
                {
                   s 
          = soap_accept(&soap);
                   
          if (s < 0)
                   {
                      soap_print_fault(
          &soap, stderr);
                      
          break;
                   }
                   fprintf(stderr, 
          "%d: accepted connection from IP=%d.%d.%d.%d socket=%d", i,
                      (soap.ip 
          >> 24)&0xFF, (soap.ip >> 16)&0xFF, (soap.ip >> 8)&0xFF, soap.ip&0xFF, s);
                   
          if (soap_serve(&soap) != SOAP_OK) // process RPC request
                      soap_print_fault(&soap, stderr); // print error
                   fprintf(stderr, "request served\n");
                   soap_destroy(
          &soap); // clean up class instances
                   soap_end(&soap); // clean up everything and close socket
                }
             }
             soap_done(
          &soap); // close master socket and detach environment
          }
          // Implementation of the "add" remote method: 
          int ns__add(struct soap *soap, double a, double b, double &result) 

             result 
          = a + b; 
             
          return SOAP_OK; 

          // Implementation of the "sub" remote method: 
          int ns__sub(struct soap *soap, double a, double b, double &result) 

             result 
          = a - b; 
             
          return SOAP_OK; 

          // Implementation of the "sqrt" remote method: 
          int ns__sqrt(struct soap *soap, double a, double &result) 

             
          if (a >= 0
             { 
                result 
          = sqrt(a); 
                
          return SOAP_OK; 
             } 
             
          else
             { 
                
          return soap_sender_fault(soap, "Square root of negative value""I can only compute the square root of a non-negative value");
             } 
          前文提到過,我們不希望為了發(fā)布基于Web Services的C語言的API而開發(fā)或應(yīng)用一個大的Web服務(wù)器。我們代碼中的main函數(shù)實現(xiàn)了一個最簡單的Web Server(基于Socket).這個Server利用gSOAP生成的API來提供針對SOAP的處理。
          下面我們把這個嵌入式的web server編譯,編譯的時候注意stdsoap2.cpp這個文件是從gSOAP包中拷貝而來,不是自動生成的,大家下載gSOAP后直接就能找到這個文件及其頭文件。
          g++ -o calcServer calc.cpp soapC.cpp soapServer.cpp stdsoap2.cpp
          一個以Web Servers形式提供的C API誕生了。
          在server端執(zhí)行./calcServer

          下面討論如何用Java1.6的自帶工具生成一個客戶端stub:
          把gSOAP生成的WSDL拷貝到我們的Java開發(fā)環(huán)境中來,按照Web Services Server中定義的端口和服務(wù)器,配置參數(shù)生成客戶端Web Services代碼:
          /usr/lib/jvm/jdk1.6.0_03/bin/wsimport -extension -httpproxy:localhost:9999 -verbose ns.wsdl

          生成后,把這個環(huán)境添加到eclipse的編譯環(huán)境中來,然后在eclipse中建一個新的類:
          class Test {
              
          public static void main(String args[]) {
                  Service service 
          = new Service();
                  
          double h = service.getService().sub(200001);
                  System.out.println(h);
              }
          }
          運行后得到結(jié)果19999.0

          總結(jié):當集成Java和C兩種平臺時,我們可以有多種解決方案,但首先我們應(yīng)該想到gSOAP因為它能夠很出色地完成任務(wù)。
          文中相關(guān)代碼:
          http://www.aygfsteel.com/Files/yangyi/gsoap.zip
          廣告:本人明年畢業(yè),正在找工作,個人簡歷:
          http://www.aygfsteel.com/Files/yangyi/My%20Resume.zip


           @2008 楊一. 版權(quán)所有. 保留所有權(quán)利

          posted on 2007-12-06 12:19 楊一 閱讀(1781) 評論(2)  編輯  收藏 所屬分類: Java SE

          評論

          # re: 淺談Java中的通信機制及與C/C++ API的集成(下) 2008-05-07 17:06 唐為奇

          為什么eclipse里無法識別import localhost._80.service.Service;
          出現(xiàn)The import localhost cannot be resolved問題啊,請指教啊!  回復(fù)  更多評論   

          # re: 淺談Java中的通信機制及與C/C++ API的集成(下)[未登錄] 2008-12-29 17:15 tom

          請問博主,客戶端是如何發(fā)現(xiàn)服務(wù)器端提供的服務(wù)的,能否結(jié)合你這里的例子說明一下。非常感謝!  回復(fù)  更多評論   

          <2007年12月>
          2526272829301
          2345678
          9101112131415
          16171819202122
          23242526272829
          303112345

          導(dǎo)航

          公告

          本人在blogjava上發(fā)表的文章及隨筆除特別聲明外均為原創(chuàng)或翻譯,作品受知識產(chǎn)權(quán)法保護并被授權(quán)遵從 知識分享協(xié)議:署名-非商業(yè)性使用-相同方式共享 歡迎轉(zhuǎn)載,請在轉(zhuǎn)載時注明作者姓名(楊一)及出處(www.aygfsteel.com/yangyi)
          /////////////////////////////////////////
          我的訪問者

          常用鏈接

          留言簿(5)

          隨筆分類(55)

          隨筆檔案(55)

          相冊

          Java

          其他技術(shù)

          生活

          最新隨筆

          搜索

          積分與排名

          最新評論

          閱讀排行榜

          評論排行榜

          自強不息


          用心 - 珍惜時間,勇于創(chuàng)造
          主站蜘蛛池模板: 加查县| 阜新市| 衡南县| 邳州市| 南平市| 岑巩县| 泰安市| 鸡泽县| 佛冈县| 葵青区| 安吉县| 红安县| 祁连县| 延庆县| 花莲县| 柏乡县| 河西区| 宜良县| 湘阴县| 富阳市| 东辽县| 西宁市| 上饶市| 东阳市| 都兰县| 海晏县| 绍兴县| 上栗县| 宁蒗| 维西| 临泉县| 布拖县| 滨海县| 陇南市| 敖汉旗| 田东县| 洛南县| 合阳县| 铁岭县| 海宁市| 绩溪县|