• <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>

            qiezi的學(xué)習(xí)園地

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

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

            前面簡(jiǎn)單寫了點(diǎn)靜態(tài)結(jié)構(gòu),這一次將主要關(guān)注動(dòng)態(tài)模型以及調(diào)用方式。

            這個(gè)系列的名字叫“為C++實(shí)現(xiàn)一個(gè)IDL”,實(shí)際上應(yīng)該叫“為C++實(shí)現(xiàn)一個(gè)Remoting”可能更好一些,說是IDL,主要是想通過宏,使用簡(jiǎn)單的類型定義達(dá)到自動(dòng)生成調(diào)用代碼的目的。

            一、首先來看看調(diào)用習(xí)慣。

            從調(diào)用習(xí)慣入手,主要是因?yàn)榭吹侥壳坝泻芏鄮?工具包在調(diào)用上都有很多不便之處。假如能在一開始就從這點(diǎn)出發(fā),就能把調(diào)用接口設(shè)計(jì)得更好一些。

            先來看看服務(wù)端如何開放一個(gè)服務(wù)。

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

            ????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;
            }


            我希望就是這么簡(jiǎn)單,客戶端調(diào)用有多種方式:
            1、?使用服務(wù)的IDL定義,直接調(diào)用:

            int?main?()
            {
            ????SOAPProxy?soap_service?(
            7911,?“l(fā)ocalhost”);

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


            這種方式比較簡(jiǎn)單,調(diào)用時(shí)會(huì)檢查是否已經(jīng)連接,然后發(fā)送調(diào)用請(qǐng)求,并處理調(diào)用結(jié)果。

            2、?服務(wù)驗(yàn)證方式:

            int?main?()
            {
            ????SOAPProxy?soap_service?(
            7911,?“l(fā)ocalhost”);
            ????TestService?test_service;
            ????soap_service.getService?(“test_service”,?
            &test_service);

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


            3、?服務(wù)發(fā)現(xiàn)方式:

            int?main?()
            {
            ????SOAPProxy?soap_service?(
            7911,?“l(fā)ocalhost”);
            ????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;
            }


            二、基本需求。

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

            看起來挺多的,其實(shí)很難接觸到這些,只需要使用宏來定義一個(gè)服務(wù),就可以通過模板的類型推導(dǎo),自動(dòng)生成這些復(fù)雜的定義。

            三、調(diào)用過程。

            以下只簡(jiǎn)單分析一下同步調(diào)用,異步調(diào)用將是以后的擴(kuò)充話題。
            根據(jù)第二節(jié)的3種不同調(diào)用過程,簡(jiǎn)要描述如下:
            1. 直接調(diào)用。

              • 生成SOAPProxy,讓它連接到遠(yuǎn)程主機(jī)。
              • 生成一個(gè)TestService對(duì)象,設(shè)置遠(yuǎn)程主機(jī)上的服務(wù)名稱,并指定使用SOAPProxy,也即使用SOAP協(xié)議。
              • 調(diào)用TestService::method1方法。根據(jù)method1的定義,把服務(wù)名稱、方法名稱、各個(gè)in參數(shù)等打包成一個(gè)“集合”,交給SOAPProxy處理。
              • SOAPProxy把這個(gè)“集合”轉(zhuǎn)換成SOAP消息,發(fā)送到遠(yuǎn)程主機(jī),阻塞線程。
              • 遠(yuǎn)程主機(jī)上的SOAPProxy對(duì)象收到數(shù)據(jù),進(jìn)行解析。當(dāng)解析出一個(gè)服務(wù)調(diào)用時(shí),把它交給TestService服務(wù)處理。
              • TestService解析出一個(gè)方法調(diào)用,把它交給Method處理。
              • Method解析出各個(gè)參數(shù),驗(yàn)證參數(shù)類型、完整性等,并執(zhí)行調(diào)用或返回錯(cuò)誤。
              • Method調(diào)用的返回信息(包括調(diào)用結(jié)果、返回值、out參數(shù)等)被打包成一個(gè)“集合”,交給TestService處理。
              • TestService處理后,交給SOAPProxy。
              • SOAPProxy把結(jié)果打包成SOAP消息,發(fā)回調(diào)用端。
              • 調(diào)用端解析SOAP消息,把OUT參數(shù)值賦給調(diào)用者提供的對(duì)象,調(diào)用完成。

              ?

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

              這種方式看起來多了一些操作,不過驗(yàn)證的好處是能夠減少調(diào)用時(shí)的異常。

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

              使用這種方式,調(diào)用端不需要服務(wù)的類型定義。

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

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

            AMI和AMD對(duì)于靜態(tài)定義的服務(wù)是有影響的,比如下面一個(gè)服務(wù):

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


            在同步調(diào)用時(shí),它的調(diào)用方式:

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


            異步調(diào)用時(shí),調(diào)用方式:

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


            正如上面演示的一樣,異步調(diào)用的結(jié)果有2種方式去處理。
            一是由線程池調(diào)用完以后,接著調(diào)用一個(gè)函數(shù)以通知結(jié)果。它不需要輪詢,不過涉及到了線程問題,增加了一些復(fù)雜性。
            另一種方式調(diào)用結(jié)束后,原調(diào)用線程在某個(gè)適當(dāng)?shù)摹皶r(shí)機(jī)”去查詢調(diào)用結(jié)果。這個(gè)時(shí)機(jī)可以是定時(shí)查詢,也可以是被線程消息通知而去處理。

            五、其它。

            這一篇加上前一篇,應(yīng)該是提到了全部的要點(diǎn)。
            目前剩下的唯一一個(gè)難點(diǎn),可能是在處理異步調(diào)用時(shí),Method的定義。
            正如上面演示的,一個(gè)方法在同步調(diào)用和異步調(diào)用時(shí),就有3種調(diào)用方式:

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


            特別地,它如何根據(jù)in和個(gè)數(shù)和out的個(gè)數(shù),產(chǎn)生那2個(gè)參數(shù)個(gè)數(shù)匹配的異步調(diào)用函數(shù)?
            再來回顧一下method1的定義:

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


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

            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
            {
            };


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

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



            這是后面要考慮的內(nèi)容,今天先想到這。

            posted on 2005-09-17 19:40 qiezi 閱讀(959) 評(píng)論(4)  編輯 收藏 引用 所屬分類: 自家破爛C++asgard項(xiàng)目
            性欧美丰满熟妇XXXX性久久久| 亚洲中文字幕久久精品无码APP| 久久久精品日本一区二区三区| 久久精品国产亚洲AV香蕉| 久久99热只有频精品8| 久久久久九国产精品| 久久大香香蕉国产| 亚洲精品美女久久久久99小说 | 狠狠色婷婷久久综合频道日韩| 无码久久精品国产亚洲Av影片 | 91久久精品无码一区二区毛片| 国产精品久久久久免费a∨| 91精品国产高清久久久久久91| 中文字幕乱码人妻无码久久| 国产伊人久久| 99久久99这里只有免费费精品| 一本大道久久香蕉成人网| 久久精品国产久精国产| 老色鬼久久亚洲AV综合| 国产亚洲精久久久久久无码77777| 久久精品成人欧美大片| 国产91色综合久久免费| 久久综合久久自在自线精品自| 日韩十八禁一区二区久久| 国产精品激情综合久久| 久久电影网一区| 久久久久中文字幕| 国产成人精品白浆久久69 | 久久无码一区二区三区少妇| 久久精品人人做人人爽电影| 久久99精品国产自在现线小黄鸭 | 精品国产热久久久福利| 久久青青草原国产精品免费 | 99久久中文字幕| 精品久久久久久无码中文字幕一区| 久久无码国产专区精品| 久久夜色精品国产亚洲| 亚洲精品无码久久久久久| 亚洲va中文字幕无码久久| 精品国产VA久久久久久久冰 | 国产精品久久久久国产A级|