• <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>
            隨筆-341  評論-2670  文章-0  trackbacks-0
                這次展示如何將一個服務器端的C++類讓客戶端調用。使用早上剛剛開發完的工具,用戶可以不用處理任何傳輸過程中的連接和編碼解碼等操作。這次實現一個四則運算的語法分析器,客戶端發送表達式,服務器端傳回語法樹(繼承樹那個模型),客戶端將語法樹傳回去,服務器端傳回運算結果。

                首先在服務器端定義語法樹:
             1 class Expression : public VL_Base
             2 {
             3 public:
             4     typedef VL_AutoPtr<Expression>        Ptr;
             5 
             6     virtual VDouble Evaluate()
             7     {
             8         return 0;
             9     }
            10 };
            11 
            12 class NumberExpression : public Expression
            13 {
            14 public:
            15     VDouble                    Number;
            16 
            17     NumberExpression()
            18     {
            19         Number=0;
            20     }
            21 
            22     NumberExpression(VDouble aNumber)
            23     {
            24         Number=aNumber;
            25     }
            26 
            27     VDouble Evaluate()
            28     {
            29         return Number;
            30     }
            31 };
            32 
            33 enum BinaryType
            34 {
            35     btAdd,
            36     btSub,
            37     btMul,
            38     btDiv
            39 };
            40 
            41 class BinaryExpression : public Expression
            42 {
            43 public:
            44     Expression::Ptr            Left;
            45     Expression::Ptr            Right;
            46     BinaryType                Type;
            47 
            48     BinaryExpression()
            49     {
            50         Type=btAdd;
            51     }
            52 
            53     BinaryExpression(Expression::Ptr aLeft , Expression::Ptr aRight , BinaryType aType)
            54     {
            55         Left=aLeft;
            56         Right=aRight;
            57         Type=aType;
            58     }
            59 
            60     VDouble Evaluate()
            61     {
            62         switch(Type)
            63         {
            64         case btAdd:
            65             return Left->Evaluate()+Right->Evaluate();
            66         case btSub:
            67             return Left->Evaluate()-Right->Evaluate();
            68         case btMul:
            69             return Left->Evaluate()*Right->Evaluate();
            70         case btDiv:
            71             return Left->Evaluate()/Right->Evaluate();
            72         default:
            73             return 0;
            74         }
            75     }
            76 };

                其次使用Combinator寫一個語法分析器:
             1 enum TokenType
             2 {
             3     ttNumber,
             4     ttAdd,
             5     ttSub,
             6     ttMul,
             7     ttDiv,
             8     ttLeft,
             9     ttRight
            10 };
            11 
            12 Expression::Ptr CreateNumber(const VL_CpToken& Token)
            13 {
            14     return new NumberExpression(VUnicodeString(Token.Start,Token.Length).ToDouble());
            15 }
            16 
            17 Expression::Ptr CreateBinary(const VL_CpPair<Expression::Ptr , VL_CpList<VL_CpPair<VL_CpToken , Expression::Ptr>>>& Input)
            18 {
            19     Expression::Ptr Result=Input.First;
            20     VL_CpList<VL_CpPair<VL_CpToken , Expression::Ptr>>::Node::Ptr Current=Input.Second.Head;
            21     while(Current)
            22     {
            23         switch(Current->Data.First.ID)
            24         {
            25         case ttAdd:
            26             Result=new BinaryExpression(Result,Current->Data.Second,btAdd);
            27             break;
            28         case ttSub:
            29             Result=new BinaryExpression(Result,Current->Data.Second,btSub);
            30             break;
            31         case ttMul:
            32             Result=new BinaryExpression(Result,Current->Data.Second,btMul);
            33             break;
            34         case ttDiv:
            35             Result=new BinaryExpression(Result,Current->Data.Second,btDiv);
            36             break;
            37         }
            38         Current=Current->Next;
            39     }
            40     return Result;
            41 }
            42 
            43 class ExpressionParser
            44 {
            45 public:
            46     Expression::Ptr Parse(VUnicodeString Input)
            47     {
            48         VL_CpLexer Lexer;
            49         Lexer
            50             <<Token(false,_UnsignedFloat,ttNumber)
            51             <<Token(false,L"+",ttAdd)
            52             <<Token(false,L"-",ttSub)
            53             <<Token(false,L"*",ttMul)
            54             <<Token(false,L"/",ttDiv)
            55             <<Token(false,L"(",ttLeft)
            56             <<Token(false,L")",ttRight)
            57             ;
            58 
            59         typedef VL_CpLexedTypes<Expression::Ptr> Types;
            60         Types::Rule Factor,Term,Expr;
            61 
            62         Factor=(CreateNumber<<=Token(ttNumber))||(Token(ttLeft)>Expr<Token(ttRight));
            63         Term=CreateBinary<<=(Factor+**((Token(ttMul)||Token(ttDiv))+Factor));
            64         Expr=CreateBinary<<=(Term+**((Token(ttAdd)||Token(ttSub))+Term));
            65         Types::Parser Parser=Expr;
            66 
            67         VL_CpLexer::_Result LexerResult=Lexer.Parse(Input.Buffer());
            68         if(LexerResult.First.Head && !LexerResult.Second.First)
            69         {
            70             Types::Parser::_FullResult ParserResult=Parser.Parse(LexerResult.First.Head,true);
            71             if(ParserResult.Head)
            72             {
            73                 return ParserResult.Head->Data.First;
            74             }
            75         }
            76         return 0;
            77     }
            78 
            79     VDouble Evaluate(Expression::Ptr Expr)
            80     {
            81         return Expr->Evaluate();
            82     }
            83 };

                最后將這4個類注冊進服務器:
             1 /*********************************************************************************************************
             2 反射
             3 *********************************************************************************************************/
             4 
             5 VL_BEGIN_INSPECTOR_DECLARATION
             6 
             7     VL_BEGIN_BASE_CLASS(Expression)
             8     VL_END_CLASS(Expression)
             9 
            10     VL_BEGIN_SUB_CLASS(NumberExpression,Expression)
            11         VL_ADD_CLASS_MEMBER(Number)
            12     VL_END_CLASS(NumberExpression)
            13 
            14     VL_BEGIN_ENUM(BinaryType,false)
            15         VL_ADD_ENUM_MEMBER(btAdd)
            16         VL_ADD_ENUM_MEMBER(btSub)
            17         VL_ADD_ENUM_MEMBER(btMul)
            18         VL_ADD_ENUM_MEMBER(btDiv)
            19     VL_END_ENUM(BinaryType)
            20 
            21     VL_BEGIN_SUB_CLASS(BinaryExpression,Expression)
            22         VL_ADD_CLASS_MEMBER(Left)
            23         VL_ADD_CLASS_MEMBER(Right)
            24         VL_ADD_CLASS_MEMBER(Type)
            25     VL_END_CLASS(BinaryExpression)
            26 
            27     VL_BEGIN_BASE_CLASS(ExpressionParser)
            28         VL_ADD_CLASS_METHOD(Parse)
            29         VL_ADD_CLASS_METHOD(Evaluate)
            30     VL_END_CLASS(ExpressionParser)
            31 
            32     VL_BEGIN_INSPECTOR_MANAGER(ExpressionManager)
            33         VL_BIND_INSPECTOR(Expression)
            34         VL_BIND_INSPECTOR(NumberExpression)
            35         VL_BIND_INSPECTOR(BinaryExpression)
            36         VL_BIND_INSPECTOR(ExpressionParser)
            37     VL_END_INSPECTOR_MANAGER
            38 
            39 VL_END_INSPECTOR_DECLARATION
            40 
            41 /*********************************************************************************************************
            42 主程序
            43 *********************************************************************************************************/
            44 
            45 void vlmain()
            46 {
            47     GetConsole()->SetTitle(L"Vczh HTTP Server");
            48     GetConsole()->SetTestMemoryLeaks(true);
            49     GetConsole()->SetPauseOnExit(false);
            50     GetConsole()->WriteLine(L"主機名稱:"+GetHostName());
            51     GetConsole()->WriteLine(L"主機地址:"+GetIpv4Address());
            52 
            53     VL_ObjectServer Server(VL_GET_INSPECTOR_MANAGER(ExpressionManager),8080,8081,L"expression");
            54     Server.Start();
            55     GetConsole()->WriteLine(L"按回車結束服務程序:");
            56     GetConsole()->WaitForEnter();
            57 }

                注意代碼配置的HTTP端口是8080,Service端口是8081。首先是服務器端的截圖:

                然后就可以使用上面的地址(或者寫成localhost,如果是本地調試的話)和端口打開一個服務器自動產生的網站,在上面可以下載已經生成的客戶端的代碼:


                建立一個客戶端工程,將這個遠程調用的庫的源代碼包含進去之后,將.h和.cpp下載了加進工程,然后修改#include的地址,就可以編譯了:

                于是我們就可以立刻調用這個類了。注意算法的實現仍然在服務器端,生成的expression.h/.cpp只負責在網絡上傳輸你的參數和服務器的結果
             1 #include "..\..\..\..\VL++\Library\Platform\VL_Console.h"
             2 #include "expression.h"
             3 
             4 using namespace vl;
             5 using namespace vl::platform;
             6 
             7 void vlmain()
             8 {
             9     GetConsole()->SetTitle(L"Vczh HTTP Client");
            10     GetConsole()->SetTestMemoryLeaks(true);
            11     GetConsole()->SetPauseOnExit(true);
            12 
            13     try
            14     {
            15         ExpressionParser Parser;
            16         VUnicodeString Input;
            17         GetConsole()->WriteLine(L"請輸入四則運算表達式,若直接回車則視為結束。");
            18         while(true)
            19         {
            20             GetConsole()->Write(L"");
            21             GetConsole()->Read(Input);
            22             if(Input==L"")
            23             {
            24                 break;
            25             }
            26             VL_AutoPtr<Expression> Expr=Parser.Parse(Input);
            27             if(Expr)
            28             {
            29                 GetConsole()->WriteLine(L"結果:"+VUnicodeString(Parser.Evaluate(Expr)));
            30             }
            31             else
            32             {
            33                 GetConsole()->WriteLine(L"出現語法錯誤。");
            34             }
            35         }
            36     }
            37     catch(const VL_ObjectClientError& e)
            38     {
            39         GetConsole()->WriteLine(L"發生錯誤:"+e.Message);
            40     }
            41     GetConsole()->WriteLine(L"結束運行。");
            42 }

                然后我們看看運行結果:

                成功了!只需要在服務器端注冊一個類,客戶端就可以這么調用了。而且無論數據結構有什么繼承還有各種各樣的容器都不成問題,還可以在不修改已有代碼的情況下,擴展成支持STL或者其他各種容器的系統。

                最后附上服務器生成的客戶端頭文件和代碼文件。首先是頭文件:
             1 /*******************************************************************************
             2 Vczh Library++ 2.0
             3 C++遠程對象客戶端::expression
             4 開發者:陳梓瀚
             5 
             6 *******************************************************************************/
             7 #ifndef VCZH_LIBRARY_PLUS_PLUS_2_0_C_PLUS_PLUS_REMOTE_OBJECT_CLIENT_EXPRESSION
             8 #define VCZH_LIBRARY_PLUS_PLUS_2_0_C_PLUS_PLUS_REMOTE_OBJECT_CLIENT_EXPRESSION
             9 
            10 #include "Library\Data\Inspector\VL_ObjectClient.h"
            11 
            12 using namespace vl;
            13 using namespace vl::collection;
            14 using namespace vl::inspector;
            15 
            16 enum BinaryType
            17 {
            18     btAdd,
            19     btDiv,
            20     btMul,
            21     btSub,
            22 };
            23 
            24 class Expression : public VL_Base
            25 {
            26 public:
            27 };
            28 
            29 class BinaryExpression : public Expression
            30 {
            31 public:
            32     VL_AutoPtr<Expression> Left;
            33     VL_AutoPtr<Expression> Right;
            34     BinaryType Type;
            35 };
            36 
            37 class ExpressionParser : public VL_ObjectClient
            38 {
            39 protected:
            40     VL_InspectorManager::Ptr FManager;
            41 
            42     VL_InspectorManager::Ptr GetInspectorManager();
            43 public:
            44     ExpressionParser();
            45 
            46     VDouble Evaluate(VL_AutoPtr<Expression> _0);
            47     VL_AutoPtr<Expression> Parse(VUnicodeString _0);
            48 };
            49 
            50 class NumberExpression : public Expression
            51 {
            52 public:
            53     VDouble Number;
            54 };
            55 
            56 #endif

                然后是代碼文件:
             1 #include "expression.h"
             2 
             3 VL_BEGIN_INSPECTOR_DECLARATION
             4 
             5     VL_BEGIN_ENUM(BinaryType,false)
             6         VL_ADD_ENUM_MEMBER(btAdd)
             7         VL_ADD_ENUM_MEMBER(btDiv)
             8         VL_ADD_ENUM_MEMBER(btMul)
             9         VL_ADD_ENUM_MEMBER(btSub)
            10     VL_END_ENUM(BinaryType)
            11 
            12     VL_BEGIN_BASE_CLASS(Expression)
            13     VL_END_CLASS(Expression)
            14 
            15     VL_BEGIN_SUB_CLASS(BinaryExpression,Expression)
            16         VL_ADD_CLASS_MEMBER(Left)
            17         VL_ADD_CLASS_MEMBER(Right)
            18         VL_ADD_CLASS_MEMBER(Type)
            19     VL_END_CLASS(BinaryExpression)
            20 
            21     VL_BEGIN_BASE_CLASS(ExpressionParser)
            22         VL_ADD_CLASS_METHOD(Evaluate)
            23         VL_ADD_CLASS_METHOD(Parse)
            24     VL_END_CLASS(ExpressionParser)
            25 
            26     VL_BEGIN_SUB_CLASS(NumberExpression,Expression)
            27         VL_ADD_CLASS_MEMBER(Number)
            28     VL_END_CLASS(NumberExpression)
            29 
            30     VL_BEGIN_INSPECTOR_MANAGER(expressionManager)
            31         VL_BIND_INSPECTOR(BinaryType)
            32         VL_BIND_INSPECTOR(Expression)
            33         VL_BIND_INSPECTOR(BinaryExpression)
            34         VL_BIND_INSPECTOR(ExpressionParser)
            35         VL_BIND_INSPECTOR(NumberExpression)
            36     VL_END_INSPECTOR_MANAGER
            37 
            38 VL_END_INSPECTOR_DECLARATION
            39 
            40 /*********************************************************************************************************
            41 ExpressionParser
            42 *********************************************************************************************************/
            43 
            44 VL_InspectorManager::Ptr ExpressionParser::GetInspectorManager()
            45 {
            46     return FManager;
            47 }
            48 
            49 ExpressionParser::ExpressionParser():VL_ObjectClient(L"192.168.11.13:8081",L"ExpressionParser")
            50 {
            51     FManager=VL_GET_INSPECTOR_MANAGER(expressionManager);
            52     SetMethodResult(L"Evaluate",FManager->GetInspector(L"VDouble"));
            53     AddMethodParameter(L"Evaluate",FManager->GetInspector(L"Expression"));
            54     SetMethodResult(L"Parse",FManager->GetInspector(L"Expression"));
            55     AddMethodParameter(L"Parse",FManager->GetInspector(L"VUnicodeString"));
            56 }
            57 
            58 VDouble ExpressionParser::Evaluate(VL_AutoPtr<Expression> _0)
            59 {
            60     VL_ObjectInspector::Ptr ResultInspector;
            61     VDouble ResultVariable;
            62     VPointer ResultData=&ResultVariable;
            63     VPointer Parameters[1];
            64     Parameters[0]=_0.Object();
            65     Invoke(L"Evaluate",Parameters,ResultInspector,ResultData);
            66     return ResultVariable;
            67 }
            68 
            69 VL_AutoPtr<Expression> ExpressionParser::Parse(VUnicodeString _0)
            70 {
            71     VL_ObjectInspector::Ptr ResultInspector;
            72     VPointer ResultData=0;
            73     VPointer Parameters[1];
            74     Parameters[0]=&_0;
            75     Invoke(L"Parse",Parameters,ResultInspector,ResultData);
            76     return (Expression*)ResultData;
            77 }
            78 

                現在只完成了單向操作,服務器端還不能調用客戶端提供的服務。等這個完成之后,就寫一個完整的Demo,然后把代碼放出來供下載。
            posted on 2009-07-03 18:07 陳梓瀚(vczh) 閱讀(4120) 評論(14)  編輯 收藏 引用 所屬分類: C++

            評論:
            # re: 實現C++遠程調用類的操作。 2009-07-03 18:26 | Len3d_
            能用來做網絡渲染否?  回復  更多評論
              
            # re: 實現C++遠程調用類的操作。 2009-07-03 18:35 | Bill Hsu
            這個很強……  回復  更多評論
              
            # re: 實現C++遠程調用類的操作。 2009-07-03 18:40 | XXOOXX
            對象打包和解包的DEMO么。
            不錯的。
              回復  更多評論
              
            # re: 實現C++遠程調用類的操作。 2009-07-03 21:55 | 陳梓瀚(vczh)
            @Len3d_
            以后加入對stream的支持,就可以了。  回復  更多評論
              
            # re: 實現C++遠程調用類的操作。 2009-07-03 23:45 | 99網上書城
            對象打包和解包的DEMO么。
            不錯的。  回復  更多評論
              
            # re: 實現C++遠程調用類的操作。 2009-07-04 00:27 | shuren99
            對象打包和解包的DEMO么  回復  更多評論
              
            # re: 實現C++遠程調用類的操作。 2009-07-04 02:32 | 路南平
            很好 學習了  回復  更多評論
              
            # re: 實現C++遠程調用類的操作。 2009-07-04 04:42 | 空明流轉
            你要能把那個類注冊去掉,就神了。  回復  更多評論
              
            # re: 實現C++遠程調用類的操作。 2009-07-05 18:00 | 巫云
            類注冊恐怕很難去掉吧,樓主這個是不是類似MS的DCOM了?  回復  更多評論
              
            # re: 實現C++遠程調用類的操作。 2009-07-05 18:09 | 陳梓瀚(vczh)
            @巫云
            類似web service  回復  更多評論
              
            # re: 實現C++遠程調用類的操作。 2009-07-06 21:09 | 凡客誠品
            不錯  回復  更多評論
              
            # re: 實現C++遠程調用類的操作。 2009-07-06 21:10 | 凡客誠品
            @99網上書城
            不錯啊你!  回復  更多評論
              
            # re: 實現C++遠程調用類的操作。 2009-07-07 22:41 | SOS
            拍手。  回復  更多評論
              
            # re: 實現C++遠程調用類的操作。 2009-11-12 21:15 | linclon
            樓主很強,很佩服!  回復  更多評論
              
            精品久久人人爽天天玩人人妻 | 国产精品久久免费| 免费精品久久天干天干| 色欲综合久久躁天天躁蜜桃| 国产精品一区二区久久精品| 久久精品国产99久久香蕉| 久久精品人人做人人爽电影| 久久精品一本到99热免费| 久久国产免费观看精品| 久久青青国产| 精品久久久久久无码中文字幕一区| 亚洲国产精久久久久久久| 久久国内免费视频| 四虎国产精品免费久久5151| 综合久久一区二区三区 | 久久午夜无码鲁丝片| 伊人久久大香线焦综合四虎| 99久久精品国产一区二区| 一本伊大人香蕉久久网手机| 99精品久久久久久久婷婷| 久久久久久国产精品免费免费 | 国产国产成人久久精品| 亚洲精品高清国产一线久久| 久久精品亚洲男人的天堂| 国产亚洲欧美精品久久久| 久久久久se色偷偷亚洲精品av| 88久久精品无码一区二区毛片 | 一级做a爰片久久毛片16| 久久久噜噜噜www成人网| 久久这里只有精品首页| 亚洲国产成人精品女人久久久| 久久99精品九九九久久婷婷| 国内精品久久久人妻中文字幕| 亚洲va中文字幕无码久久不卡| 思思久久精品在热线热| 亚洲国产成人精品91久久久 | 国产成人久久精品麻豆一区| 色欲久久久天天天综合网 | 国内精品九九久久精品| 久久精品国产亚洲av麻豆图片| 久久久久久午夜精品|