青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

qiezi的學習園地

AS/C/C++/D/Java/JS/Python/Ruby

  C++博客 :: 首頁 :: 新隨筆 ::  ::  :: 管理 ::

前面簡單寫了點靜態結構,這一次將主要關注動態模型以及調用方式。

這個系列的名字叫“為C++實現一個IDL”,實際上應該叫“為C++實現一個Remoting”可能更好一些,說是IDL,主要是想通過宏,使用簡單的類型定義達到自動生成調用代碼的目的。

一、首先來看看調用習慣。

從調用習慣入手,主要是因為看到目前有很多庫/工具包在調用上都有很多不便之處。假如能在一開始就從這點出發,就能把調用接口設計得更好一些。

先來看看服務端如何開放一個服務。

int?main?()
{
????
//?發布為SOAP服務,先生成一個服務容器。
????
//?服務將發布在localhost的7911上,localhost用來綁定loopback網卡。
????SOAPProxy?soap_service?(7911,?“localhost”);

????TestService?test_service;?
????soap_service.addService??(“test_service”,?
&test_service);

????TestService?service1;
????soap_service.addService?(“HelloService”,?
&service1);

????
try{
????????soap_service.run?();
????}?
catch?(SocketException&?e)
????{
????}?
catch?(SignalException&?e)
????{
????}

????
return?0;
}


我希望就是這么簡單,客戶端調用有多種方式:
1、?使用服務的IDL定義,直接調用:

int?main?()
{
????SOAPProxy?soap_service?(
7911,?“localhost”);

????
try{
????????TestService?test_service?(“test_service”,?
&soap_service);
????????test_service.method1?(
/**/);
????}?
catch?(SocketException&?e)
????{
????}
????
return?0;
}


這種方式比較簡單,調用時會檢查是否已經連接,然后發送調用請求,并處理調用結果。

2、?服務驗證方式:

int?main?()
{
????SOAPProxy?soap_service?(
7911,?“localhost”);
????TestService?test_service;
????soap_service.getService?(“test_service”,?
&test_service);

????
if?(test_service)
????{
????????
try{
????????????test_service.method1?(
/**/);
????????}?
catch?(SocketException&?e)
????????{
????????}
????}
????
return?0;
}


3、?服務發現方式:

int?main?()
{
????SOAPProxy?soap_service?(
7911,?“localhost”);
????vector?
<string>?services_name?=?soap_service.getServiceNames?();
????
//?
????IService*?test_service?=?soap_service.getService?(“test_service”);
????
if?(test_service)
????{
????????vector?
<string>?methods?=?test_service->getMethodNames?();
????????IMethod
*?method?=?test_service->getMethod?(“method1”);
????????vector?
<Type*>?types?=?method->getParameterType?s()
????????method
->addArg?(3);
????????method
->addArg?(4);
????????
//?
????????method->invoke?();
????????
//?
????}
????
return?0;
}


二、基本需求。

簡單分析一下,上面一共涉及了哪些類型?
IProxy:
這是所有Proxy類的基類(和接口),它可以容納多個服務對象,提供服務綁定、服務查詢、服務發現、服務驗證。
IService:
所有Service類的基類,可以容納多個方法(Method),提供方法查詢、服務驗證。
IMethod:
所有Method模板類的基類,容納多個參數,包括返回值,可通過查詢參數類型獲得方法的類型定義。
IParameter:
所有參數的基類,包含一個參數類型描述和一個參數值。
IType:
所有類型的基類,預定義了一些基本類型,可自定義類型。

看起來挺多的,其實很難接觸到這些,只需要使用宏來定義一個服務,就可以通過模板的類型推導,自動生成這些復雜的定義。

三、調用過程。

以下只簡單分析一下同步調用,異步調用將是以后的擴充話題。
根據第二節的3種不同調用過程,簡要描述如下:
  1. 直接調用。

    • 生成SOAPProxy,讓它連接到遠程主機。
    • 生成一個TestService對象,設置遠程主機上的服務名稱,并指定使用SOAPProxy,也即使用SOAP協議。
    • 調用TestService::method1方法。根據method1的定義,把服務名稱、方法名稱、各個in參數等打包成一個“集合”,交給SOAPProxy處理。
    • SOAPProxy把這個“集合”轉換成SOAP消息,發送到遠程主機,阻塞線程。
    • 遠程主機上的SOAPProxy對象收到數據,進行解析。當解析出一個服務調用時,把它交給TestService服務處理。
    • TestService解析出一個方法調用,把它交給Method處理。
    • Method解析出各個參數,驗證參數類型、完整性等,并執行調用或返回錯誤。
    • Method調用的返回信息(包括調用結果、返回值、out參數等)被打包成一個“集合”,交給TestService處理。
    • TestService處理后,交給SOAPProxy。
    • SOAPProxy把結果打包成SOAP消息,發回調用端。
    • 調用端解析SOAP消息,把OUT參數值賦給調用者提供的對象,調用完成。

    ?

  2. 服務驗證方式。
    • 生成SOAPProxy,讓它連接到遠程主機。
    • 生成TestService對象,調用SOAPProxy的getService驗證版本。
    • SOAPProxy把TestService對象的信息(名稱、成員及基類型等)發送到遠程主機,阻塞。
    • 遠程主機解析收到的信息,查找服務名,并比較查找到的服務類型與解析得到的類型。
    • 比較結果發回給調用端。
    • 調用端接著采用直接調用的方式,調用遠程服務。

    這種方式看起來多了一些操作,不過驗證的好處是能夠減少調用時的異常。

  3. 服務發現方式。
    • 生成SOAPProxy,讓它連接到遠程主機。
    • 查詢遠程開放的服務名稱。(可省略)
    • 查找特定服務,得到服務描述信息。
    • 查找服務中的方法,得到方法描述信息。
    • 壓入各個參數,并執行調用。
    • 調用前先判斷參數是否與描述一致,然后調用SOAPProxy生成SOAP消息,發送到遠程主機,阻塞。
    • 遠程主機解析出調用。。。后面過程與第1種方式相同,遠程主機并不知道客戶端使用的是哪種方式來調用。遠程主機處理結束,將返回SOAP消息給調用端。
    • 調用端解析出調用結果,并把各個OUT參數的值賦給method對象。

    使用這種方式,調用端不需要服務的類型定義。

四、異步調用/異步分派(AMI/AMD)。

同步調用時,調用端線程需要等待調用結果,服務端線程也要等待調用結束返回,才處理下一個調用。
為了在服務調用期間讓線程能做更多的事:
調用端把調用交給線程池完成,并在調用完成后采用某種機制通知線程處理結果,或者直接由線程池中的調用線程調用結果處理函數。這種方式稱為AMI(異步方法調用)。
服務端主線程則把接收到的消息解析后,放入處理隊列,由線程池去處理調用過程。當調用完成后,結果放入結果隊列,由主線程處理成消息,發送回調用端。這種方式稱為AMD(異步方法分派)。
調用端和服務端依舊是使用通訊協議來溝通,雙方都不知道對方是否采用了異步方式。

AMI和AMD對于靜態定義的服務是有影響的,比如下面一個服務:

struct?TestService
{
????Method?
<void(in<int>,?out<int>)>?method1;
}


在同步調用時,它的調用方式:

TestService?test_service;
int?a;
service.method1?(
3,?a);?//?或者?service.method1?(3,?&a),打算兼容這2種方式。


異步調用時,調用方式:

void?method1_result?(int,?int);
TestService?test_service;
test_service.method1.async_call(
3,?method1_result);?//?調用完成后,讓調用線程去調用method1_result通知調用結果。
//?或者像下面
IMethod*?result?=?test_service.method1.async_call?(3);
while?(!result->done())??//?還有很多好辦法,這里只是為了簡單。
{
????sleep?(
1);
}
cout?
<<?result->getArg(1)->toInt();?


正如上面演示的一樣,異步調用的結果有2種方式去處理。
一是由線程池調用完以后,接著調用一個函數以通知結果。它不需要輪詢,不過涉及到了線程問題,增加了一些復雜性。
另一種方式調用結束后,原調用線程在某個適當的“時機”去查詢調用結果。這個時機可以是定時查詢,也可以是被線程消息通知而去處理。

五、其它。

這一篇加上前一篇,應該是提到了全部的要點。
目前剩下的唯一一個難點,可能是在處理異步調用時,Method的定義。
正如上面演示的,一個方法在同步調用和異步調用時,就有3種調用方式:

service.method1?(3,?a);
test_service.method1.async_call(
3,?method1_result);
IMethod
*?result?=?test_service.method1.async_call?(3);


特別地,它如何根據in和個數和out的個數,產生那2個參數個數匹配的異步調用函數?
再來回顧一下method1的定義:

Method?<void(in<int>,?out<int>)>?method1;


顯然有一定的復雜性,不過我認為還是可以處理掉的。拿3個參數的偏特化版本來說明:

template?<class?Ret,?class?A,?class?B,?class?C>
class?Method?<Out<Ret>(A,B,C)>?:?public?MethodBase?<Out<Ret>,A,B,C>
{
};

template?
<class?Ret=NullType,?class?A=NullType,?class?B=NullType,?class?C=NullType,?class?D=NullType,?IN_COUNT=InCount<?A,B,C,D>::value?>
class?MethodBase
{
};


通過對MethodBase類的IN_COUNT參數定義偏特化,即可定義出這些不同的版本。

當然僅僅是知道了IN參數的個數,還沒有提取出IN參數的類型,所以還不能生成函數的原型,或許需要把typelist加進來了(loki中的那個)。



這是后面要考慮的內容,今天先想到這。

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            欧美日韩调教| 亚洲免费不卡| 亚洲国产二区| 伊人久久久大香线蕉综合直播 | 久久偷窥视频| 久久久精品日韩| 久久久91精品国产一区二区精品| 欧美在线看片| 久久躁日日躁aaaaxxxx| 看欧美日韩国产| 欧美成人免费在线| 亚洲精品久久久久久久久久久久久 | 久久男女视频| 亚洲国产成人av好男人在线观看| 亚洲国产高清视频| 久久精品国产一区二区电影| 久久青草福利网站| 欧美精品久久久久久久免费观看| 欧美午夜精品电影| 黄色av日韩| 在线一区视频| 久久亚洲精品伦理| 亚洲免费成人av电影| 欧美在线高清| 久久久精品一品道一区| 国产在线一区二区三区四区| 亚洲国产欧美在线人成| 亚洲图色在线| 免费亚洲一区| 亚洲制服少妇| 久久久久www| 亚洲盗摄视频| 西瓜成人精品人成网站| 欧美精品日韩三级| 国语自产精品视频在线看| 一区二区三区精品久久久| 午夜精品99久久免费| 女生裸体视频一区二区三区| 亚洲午夜激情网页| 欧美成人午夜| 国产亚洲二区| 这里只有精品在线播放| 老司机免费视频久久| 日韩亚洲一区在线播放| 久久久久久噜噜噜久久久精品| 欧美日本久久| 国产亚洲激情在线| 中国成人黄色视屏| 欧美在线视频一区二区| 欧美国产亚洲视频| 亚洲欧美日韩综合一区| 欧美大片va欧美在线播放| 国产精品卡一卡二| 91久久精品一区| 国产欧美高清| 亚洲国产日韩欧美综合久久| 亚洲一区免费观看| 欧美sm重口味系列视频在线观看| av不卡在线看| 久久婷婷蜜乳一本欲蜜臀| 国产精品国产三级国产aⅴ无密码| 一色屋精品视频在线看| 欧美一区二区观看视频| 亚洲人成7777| 久久久综合激的五月天| 欧美电影免费观看网站 | 亚洲一区二区免费看| 久久精品亚洲精品| 国产精品乱子久久久久| 国产精品久久久久秋霞鲁丝| 在线观看成人小视频| 久久久99爱| 亚洲一区3d动漫同人无遮挡| 欧美猛交免费看| 亚洲国产精品精华液网站| 欧美国产日韩免费| 国产欧美一区二区三区久久人妖 | 性欧美大战久久久久久久免费观看 | 亚洲午夜精品| 欧美成人精品1314www| 亚洲女同同性videoxma| 欧美精品少妇一区二区三区| 精品动漫一区二区| 久久9热精品视频| 亚洲一区二区三区四区视频 | aaa亚洲精品一二三区| 欧美成年视频| 欧美视频中文字幕在线| 亚洲自拍啪啪| 久久久另类综合| 亚洲国内精品在线| 中文一区字幕| 国产亚洲精品久久飘花| 亚洲人成网站999久久久综合| 美女在线一区二区| 亚洲午夜视频在线| 亚洲无线一线二线三线区别av| 国产一区二区三区四区在线观看 | 久久亚洲国产精品日日av夜夜| 久久精品国产77777蜜臀| 雨宫琴音一区二区在线| 欧美国产日韩精品免费观看| 亚洲欧美资源在线| 午夜视频精品| 国产精品乱码人人做人人爱| 亚洲欧美激情视频在线观看一区二区三区 | 性欧美大战久久久久久久免费观看| 国产精品专区h在线观看| 久久免费黄色| 欧美国产乱视频| 亚洲综合三区| 久久久久综合网| 一本久道久久综合中文字幕| 夜夜爽av福利精品导航| 国产欧美日韩亚洲一区二区三区| 久久久久久午夜| 欧美激情第二页| 欧美一区视频| 欧美成人精品一区二区三区| 亚洲狼人精品一区二区三区| 亚洲性xxxx| 国产精品色一区二区三区| 免费视频一区| 亚洲午夜国产一区99re久久| 久久国产福利国产秒拍| 亚洲三级视频| 亚洲一区在线播放| 在线观看国产日韩| 一区二区三区 在线观看视频| 国产欧美日韩三级| 久久精品国产一区二区电影| 欧美激情91| 欧美成人激情视频| 午夜日韩在线观看| 欧美国产精品劲爆| 久色成人在线| 国产精品美女久久久久久2018| 久久久久久网址| 国产精品每日更新| 亚洲高清视频中文字幕| 国产伦精品一区二区三区免费| 亚洲国产三级网| 红桃av永久久久| 亚洲自拍偷拍视频| 狠狠综合久久av一区二区老牛| 亚洲国产欧美国产综合一区| 一区二区三区无毛| 午夜精品国产更新| 亚洲欧美日韩精品| 欧美日韩国产一区二区三区地区| 久久人人97超碰人人澡爱香蕉 | 欧美在线观看视频在线| 欧美激情一二三区| 鲁大师成人一区二区三区 | 999亚洲国产精| 最新中文字幕一区二区三区| 亚洲精品一区二区在线| 久久大香伊蕉在人线观看热2| 亚洲国产日韩欧美在线动漫 | 亚洲三级免费观看| 国产日产欧美a一级在线| 久久躁日日躁aaaaxxxx| 国产美女诱惑一区二区| 亚洲欧美精品伊人久久| 亚洲欧美日韩国产中文在线| 国产精品r级在线| 亚洲一区二区3| 香蕉久久夜色精品国产| 国产精品一卡二| 欧美一级久久久久久久大片| 欧美一级大片在线免费观看| 牛夜精品久久久久久久99黑人| 欧美国产精品人人做人人爱| 91久久精品国产91久久| 女女同性精品视频| 久久婷婷丁香| 亚洲天堂网在线观看| 国产精品毛片| 久久精品1区| 9l视频自拍蝌蚪9l视频成人| 免费亚洲网站| 一区二区日本视频| 久久国产婷婷国产香蕉| 国产精品va在线播放我和闺蜜| 亚洲风情亚aⅴ在线发布| 亚洲精品日韩精品| 欧美视频在线免费| 亚洲欧美高清| 男人的天堂亚洲| 日韩视频第一页| 欧美午夜精品久久久| 欧美在线观看网址综合| 亚洲国产成人午夜在线一区| 亚洲国产天堂网精品网站| 久久天天躁狠狠躁夜夜爽蜜月 | 国产噜噜噜噜噜久久久久久久久| 亚洲六月丁香色婷婷综合久久| 亚洲欧美一区二区三区久久 | 香蕉乱码成人久久天堂爱免费| 欧美黄色aaaa|