<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      XML-RPC 實現C++和C#交互

      我們通常會面對這樣的問題:整合不同平臺或不同類庫,這些類庫可能來自不同的語言,甚至不同的操作系統。 如何解決這類棘手的問題呢?

      一.方案介紹

       

               解決不同語言交互的方法有不少,對我了解的windows系統和.NET平臺,有以下幾種做法:

      • P/Invoke: 調用native cpp的方法,處在同一個內存區間,訪問方便,但包裝困難,可能拋出運行時異常。
      • 讀寫文件:通過一頭讀文件,一頭寫文件的方式實現交互。諸位別笑,本科時候我就用過這種方式解決問題。
      • 命名管道/socket: 通過字節數組的方式實現交互,命名管道是windows系統提供的功能,可提供安全快捷的程序間交互。socket不依賴于操作系統,只要給定包格式,在任何支持socket的語言平臺下都能支持。但缺點也很明顯,如果交互復雜,那么解析這種byte[]數組將會非常復雜而且難以維護。
      • RPC: 又稱之為遠程過程調用,也是我們今天的主角。

            數據即程序,RPC說白了依舊是傳遞數據的過程,只是過程在代碼上更像函數調用。如下圖:

      image

            目前主流的RPC有兩種: XML和JSON。 XML是曾經的主角,兼容性更好。但如今移動互聯網要求數據流量要小,而XML的缺點也隨之暴露出來,JSON由于節省數據(大大減少了包頭和標記的開銷),如今變得更受歡迎。新浪微博API,如今全部升級為JSON了。 RPC的實質是http協議,它封裝了底層實現的細節,能讓我們將注意力放在應用邏輯的實現,而非建立連接這樣的問題。

            RPC的優點很多,其中我最喜歡的是它的容器,聲明一個Array,里面可以塞任何你想要的數據,int,string,double,struct甚至另外一個array都可以。當然,不能傳遞抽象類或接口,畢竟不是同一內存區域。

            本文我們只介紹XML-RPC實現C++和C#兩個應用程序之間的交互。JSON的C#版本Jayrock對RPC的支持,尤其是對非ASP.NET環境幾乎沒有,連一篇像樣的文檔都找不到,所以我們僅僅討論XML-RPC。

         

      二. 方案實現

                     我們打算將C#作為客戶端,C++作為服務器端。

         1. C++的服務器實現

                     我們在VS2010中新建C++工程,將附件中的XMLRPC.LIB靜態庫拷入當前工程文件夾,設置當前工程為release模式。同時在C++工程設置中,添加兩個lib引用: xmlrpc.lib, ws2_32.lib

      之所以用release模式,是因為在debug模式下xmlrpc.lib庫會出現如下的編譯錯誤:花了很久時間都沒解決,如果有大神能幫助解決這個問題,請一定留言.

      1>  All outputs are up-to-date.
      1>XmlRpc.lib(XmlRpcServer.obj) : error LNK2038: mismatch detected for '_ITERATOR_DEBUG_LEVEL': value '0' doesn't match value '2' in HelloServer.obj
      1>XmlRpc.lib(XmlRpcUtil.obj) : error LNK2038: mismatch detected for '_ITERATOR_DEBUG_LEVEL': value '0' doesn't match value '2' in HelloServer.obj
      1>XmlRpc.lib(XmlRpcServerMethod.obj) : error LNK2038: mismatch detected for '_ITERATOR_DEBUG_LEVEL': value '0' doesn't match value '2' in HelloServer.obj
      1>XmlRpc.lib(XmlRpcValue.obj) : error LNK2038: mismatch detected for '_ITERATOR_DEBUG_LEVEL': value '0' doesn't match value '2' in HelloServer.obj
      1>XmlRpc.lib(XmlRpcDispatch.obj) : error LNK2038: mismatch detected for '_ITERATOR_DEBUG_LEVEL': value '0' doesn't match value '2' in HelloServer.obj
      1>XmlRpc.lib(XmlRpcServerConnection.obj) : error LNK2038: mismatch detected for '_ITERATOR_DEBUG_LEVEL': value '0' doesn't match value '2' in HelloServer.obj
      1>XmlRpc.lib(XmlRpcSocket.obj) : error LNK2038: mismatch detected for '_ITERATOR_DEBUG_LEVEL': value '0' doesn't match value '2' in HelloServer.obj
      1>XmlRpc.lib(XmlRpcSource.obj) : error LNK2038: mismatch detected for '_ITERATOR_DEBUG_LEVEL': value '0' doesn't match value '2' in HelloServer.obj

      image1

       

      再將對應的庫頭文件加入到項目中,完成后如下圖所示:

      image

      現在C#程序員普遍已經忘掉了怎么編譯和使用C++靜態庫,我也是其中之一,如果你在上面幾步遇到困難,不妨查看相關資料。

      接下來,我們將開始編寫工作代碼:

      首先是添加頭文件引用,一般只要引用XMLRPC.H和XMLRPCVALUE.H即可, 同時聲明一個全局的XmlRpcServer 服務。(實在太不習慣C++中不new就能創建實例的語法了)

      #include  "RPC/XmlRpc.h"
      #include "RPC/XmlRpcValue.h"
      #include <iostream>
      #include <stdlib.h>
      
      using namespace XmlRpc;
      
      // The server
      XmlRpcServer s;

      添加主函數:

      int main()
      {
          /*if (argc != 2) {
              std::cerr << "Usage: HelloServer serverPort\n";
              return -1;
          }*/
          //int port = atoi(argv[1]);
          int port=2567;
          XmlRpc::setVerbosity(3);
      
          // Create the server socket on the specified port
          s.bindAndListen(port);
      
          // Enable introspection
          s.enableIntrospection(true);
      
          // Wait for requests indefinitely
          s.work(-1.0);
      
          return 0;
      }
          設置端口,綁定端口和啟動.這些都沒什么好說的。值得注意的是調試等級,setVerbosity。等級越高,輸出信息越詳細,最高等級可輸出完整的xml交互文件供調試,但會嚴重拖累系統速度的。在你測試功能完畢后,不妨將其設為0。

             接下來我們創建幾個類,來實現服務端功能:

      // A variable number of arguments are passed, all doubles, result is their sum.
      class Sum : public XmlRpcServerMethod
      {
      public:
          Sum(XmlRpcServer* s) : XmlRpcServerMethod("Sum", s) {}
      
          void execute(XmlRpcValue& params, XmlRpcValue& result)
          {
              int nArgs = params.size();
              double sum = 0.0;
              for (int i=0; i<nArgs; ++i)
                  sum += double(params[i]);
              result = sum;
          }
      } sum(&s);

            所有功能都以繼承于XmlRpcServerMethod類,同時改寫其execute函數。 有點意思的是,這個XmlRPCValue數據類型,是類似C#的Dictionary,或JAVA的hashset。  你可以通過類似C#索引器(字典)的方式,添加或讀取該結構中的內容。比如上面的params[i]。由于代碼簡單,就不多做詳細解釋。

            類后跟了一個實例,sum(&s),這樣就在服務器中注冊了該功能。

          再創建一個類,來實現字符串操作:

      // One argument is passed, result is "Hello, " + arg.
      class HelloName : public XmlRpcServerMethod
      {
      public:
          HelloName(XmlRpcServer* s) : XmlRpcServerMethod("HelloName", s) {}
      
          void execute(XmlRpcValue& params, XmlRpcValue& result)
          {
              std::string resultString = "Hello, ";
              resultString += std::string(params[0]);
              result = resultString;
          }
      } helloName(&s);

          也不多做解釋了。

          我們再看一下,怎么存取RPC中的字典和數組,這才是精髓部分:

      class StructData : public XmlRpcServerMethod
      {
      public:
          StructData(XmlRpcServer* s) : XmlRpcServerMethod("GetStruct", s) {}
      
          void execute(XmlRpcValue& params, XmlRpcValue& result)
          {
               
          XmlRpcValue A;
          A.setSize(2);
      
          A[0]["a"]=123;
          A[0]["b"]=456;
          A[1]["a"]=43;
          A[1]["b"]=425;
               
              result["a"]=A;
              result["b"]=123;
          }
      } structData(&s);

         設置字典時,是不需要指定其size的,但若設定的是數組,則必須使用setsize方法設定其大小。字典的值也可包含另外一個XmlRpcValue 結構體。

         RPC中可以很好的處理字符串,int,double, datetime類型,但枚舉類型的支持并不好,我建議直接傳int.

        

        完成了這三個服務后,我們來編寫C#的客戶端。

       

          2. C# RPC客戶端實現:

               新建一個C#工程,創建以下的接口類:

      public interface IRPCMethod
      {
        [XmlRpcMethod("HelloName")]
        string HelloName(string Name);
      
        [XmlRpcMethod("Sum")]
        double Sum(double a,double b);
      
        [XmlRpcMethod("GetStruct")]
         XmlRpcStruct GetStruct(); 
      }

      當然,要引用CookComputing.XmlRpc庫。 使用接口類的作用是剝離RPC對系統的影響,讓系統可以“透明的”調用RPC代碼。值得注意的是,名稱必須與C++中的名稱一致,否則會出現找不到方法的異常。

          我們注冊客戶端服務:

      var chnl = new HttpChannel(null, new XmlRpcClientFormatterSinkProvider(), null);
              ChannelServices.RegisterChannel(chnl, false);
      
              var svr = (IRPCMethod)Activator.GetObject(typeof(IRPCMethod), "http://localhost:2567/");
              Console.WriteLine("成功注冊信道");
              string ret = svr.HelloName("haha");
              Console.WriteLine("調用helloName方法:" + ret);
              double result = svr.Sum(23, 18);
              Console.WriteLine("調用Sum方法:" + result.ToString());
      
              XmlRpcStruct result2 = svr.GetStruct();

         至于result2結構體,你可以通過調試來查看具體的運行結果。

         image

      在服務器端,可以看到調用所花費的流量和方法名稱。

      三. 其他

      這里我們關注一些額外的問題:

      1.流量

            RPC的一種場景是本地不同程序調用,這種情況下速度很快。但在跨機器或是移動設備上,就必須考慮流量因素了。XML的“性價比”并不高:

      <?xml version="1.0"?>
      <methodCall>
          <methodName>echo</methodName>
          <params>
              <param><value><string>Hello Chris</string></value></param>
              <param><value><i4>123</i4></value></param>
              </params>
          </methodCall>

        實際的有用數據,僅占所有字節數的5%,甚至更少,除非是大批量的傳輸本文數據。如果是流量敏感,推薦使用JSON.

          2. 性能

          我們當然要關心,RPC在本機調用會有多快?和哪些因素敏感? 筆者配置是i7 2600K,  8GB DDR, Gbps網絡適配器,VS的debug模式。在執行Sum操作時,一千次耗時4.3ms。 在執行更復雜的結構體傳遞(大概有20個double,三個string,兩個int時), 千次耗時5.8ms。

             因此,可以得知,XML的轉換和解析幾乎不耗時,建立連接后,執行一次在ms量級,對數據結構復雜程度不敏感,因此,若是實時性敏感應用,建議一次性多傳些數據。

        3. 兼容性

             筆者發現,RPC的兼容性并不太好,在和JAVA采用RPC交互時,就遇到了困難,”XML解析異常”。JSON的的兼容性不見得比XML更好,實際操作更是問題多多。涉及RPC的社區,普遍文檔較少,例子不全,出現問題也不好排查,更沒有太多跨語言的RPC實例。因此,如果你能用P/Invoke, 還是推薦用直接調用的做法。 RPC肯定還是比byte流的socket方便很多。

         四 .總結和源代碼下載

             RPC將原本復雜的數據傳輸問題簡化了,使我們從復雜的數據包結構,JAVA和C的double編碼和socket傳輸中脫離出來,提供了更簡單方便的方案。但必須看到,它并不完善,我們只能一步步的探索。 

           另外想問一句,Unity3D的RPC是何種格式?

            有任何問題,歡迎隨時交流。

            源代碼下載:

           https://files.cnblogs.com/buptzym/XML_RPC.rar

      posted @ 2012-11-10 18:33  FerventDesert  閱讀(12934)  評論(21)    收藏  舉報
      主站蜘蛛池模板: 中文字幕亚洲国产精品| 巴林左旗| 亚洲激情视频一区二区三区 | 内射中出无码护士在线| 性色av无码久久一区二区三区| 成人亚洲a片v一区二区三区动漫| 国产亚洲精品福利在线无卡一| 国产一区二区三区高清视频| 在线观看国产成人AV天堂| 日本乱子人伦在线视频| 国产精品小粉嫩在线观看| 狠狠亚洲色一日本高清色| 亚洲国产日韩精品一区二区三区 | 亚洲一区二区三级av| 中文字幕国产精品日韩| 欧美激情a∨在线视频播放| 亚洲天堂一区二区三区三州| 无码免费大香伊蕉在人线国产| 沅江市| 亚洲V天堂V手机在线| 东方四虎在线观看av| 日本熟妇人妻一区二区三区 | 日本不卡的一区二区三区| 人妻系列无码专区69影院| 国产精品小粉嫩在线观看| 亚洲精品天堂在线观看| 国产一区二区四区不卡| 亚洲精品中文综合第一页| 久久99精品久久久久久青青| 依依成人精品视频在线观看| 亚洲2022国产成人精品无码区| 日韩在线视频网| 久久不见久久见免费视频观看| 麻豆a级片| 999国产精品一区二区| 久久男人av资源站| 亚洲国产精品一区二区第一页| 中文字幕制服国产精品| 象州县| 久久久国产成人一区二区| 国语做受对白XXXXX在线|