• <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  評(píng)論-2670  文章-0  trackbacks-0

                今天展示一下如何使用這里描寫(xiě)的庫(kù)實(shí)現(xiàn)一個(gè)簡(jiǎn)單的聊天工具。Callback Interface是昨晚才加的,但是還有一些features沒(méi)實(shí)現(xiàn),等做完了再做一個(gè)Demo,然后提供源代碼。

                使用這個(gè)庫(kù)開(kāi)發(fā)網(wǎng)絡(luò)程序的步驟如下:
                1:將需要提供給客戶端調(diào)用的功能封裝成類,實(shí)現(xiàn)在服務(wù)器端,然后注冊(cè)需要的類、類成員變量和類成員函數(shù)。
                2:服務(wù)器創(chuàng)建VL_ObjectServer,并將注冊(cè)的類提供給它,然后運(yùn)行。
                3:打開(kāi)http://localhost:PORT/SERVER/index.htm下載服務(wù)器端需要的CallbackProxy類。當(dāng)類需要客戶端提供Callback的時(shí)候,就可以用CallbackProxy來(lái)調(diào)用它。這里CallbackProxy是自動(dòng)生成的。
                4:創(chuàng)建客戶端工程,在上面那個(gè)網(wǎng)址下載生成的服務(wù)器端的類的Proxy。這個(gè)Proxy負(fù)責(zé)連接服務(wù)器并把所需要的數(shù)據(jù)序列化之后發(fā)送過(guò)去。服務(wù)器端的VL_ObjectServer負(fù)責(zé)解讀序列化的內(nèi)容,然后調(diào)用客戶端實(shí)現(xiàn)的那些服務(wù)類。
                5:寫(xiě)一個(gè)UI調(diào)用下載的服務(wù)類的Proxy。
                6:運(yùn)行它們。
                實(shí)際上就是把他們當(dāng)成同一個(gè)程序來(lái)寫(xiě),然后這個(gè)庫(kù)提供了很多方便的功能讓客戶端可以直接調(diào)用服務(wù)器端寫(xiě)的類,中間的鏈接和傳輸不需要自己處理,完全是自動(dòng)的。

                首先我們定義這個(gè)聊天工具的接口。聊天工具登錄的時(shí)候服務(wù)器會(huì)自動(dòng)分配一個(gè)名稱,用戶可以隨后更改。然后剩下的只有兩個(gè)操作:發(fā)送信息和退出登錄。我們默認(rèn)程序關(guān)閉的時(shí)候退出登錄。于是可以先做一個(gè)User類,然后做一個(gè)Service類,Service調(diào)用Callback來(lái)告訴其他用戶某人發(fā)送了信息:

             1 class RoaTalkUser : public VL_Base
             2 {
             3 public:
             4     typedef VL_AutoPtr<RoaTalkUser>                    Ptr;
             5     typedef VL_List<Ptr , false , RoaTalkUser*>        List;
             6     typedef VL_ListedMap<VUnicodeString , Ptr>        StringMap;
             7 
             8     VUnicodeString                    Name;
             9     RoaTalkService*                    Owner;
            10 };
            11 
            12 class RoaTalkCallback : public VL_ObjectCallback
            13 {
            14 public:
            15     virtual void                    Say(RoaTalkUser::Ptr User , VUnicodeString Message);
            16     virtual void                    Login(RoaTalkUser::Ptr User);
            17     virtual void                    Logout(RoaTalkUser::Ptr User);
            18     virtual void                    Rename(VUnicodeString OldName , RoaTalkUser::Ptr User);
            19 };
            20 
            21 class RoaTalkService : public VL_ObjectService
            22 {
            23 protected:
            24     VUnicodeString                    FName;
            25     RoaTalkCallback*                FCallback;
            26 
            27     void                            Initialize();
            28 public:
            29     typedef VL_List<RoaTalkService* , true>            List;
            30 
            31     RoaTalkService();
            32     ~RoaTalkService();
            33 
            34     RoaTalkCallback*                GetCallback();
            35 
            36     VUnicodeString                    GetCurrentName();
            37     VBool                            SetCurrentName(VUnicodeString Name);
            38     void                            Say(VUnicodeString Message);
            39     VL_AutoPtr<RoaTalkUser::List>    GetUsers();
            40 };

                這只是給客戶端調(diào)用的外殼。因?yàn)槊恳粋€(gè)客戶端連接的時(shí)候,系統(tǒng)就會(huì)創(chuàng)建一個(gè)RoaTalkService類,所以還需要一個(gè)全局變量來(lái)記錄所有的Service類(未來(lái)可能會(huì)提供Feature來(lái)避免這種全局變量的產(chǎn)生)。這個(gè)全局的服務(wù)類是需要鎖的:
             1 class RoaTalkServer : public VL_Base
             2 {
             3 protected:
             4     RoaTalkUser::StringMap            FUsers;
             5     VL_SynCriticalSection            FServerLock;
             6 public:
             7     RoaTalkServer();
             8     ~RoaTalkServer();
             9 
            10     VBool                            CreateUser(VUnicodeString Name , RoaTalkService* Service);
            11     VBool                            DestroyUser(VUnicodeString Name);
            12     VBool                            RenameUser(VUnicodeString OldName , VUnicodeString NewName);
            13     VL_AutoPtr<RoaTalkUser::List>    GetUsers();
            14     VBool                            Say(VUnicodeString Name , VUnicodeString Message);
            15 };
            16 
            17 extern void                            CreateRoaTalkServer();
            18 extern void                            DestroyRoaTalkServer();
            19 extern RoaTalkServer*                GetRoaTalkServer();

                實(shí)現(xiàn)他們是很容易的。Service通過(guò)調(diào)用CreateUser、DestroyUser、RenameUser和Say來(lái)完成SetCurrentName和Say兩個(gè)操作。Server(注意不是Service)在被調(diào)用的時(shí)候,通過(guò)向其他Service->GetCallback()來(lái)通知其他客戶端某個(gè)人做了什么事情。注意雖然代碼是在服務(wù)器端,但是RoaTalkCallback的實(shí)現(xiàn)是在客戶端。下面會(huì)告訴大家如何把兩邊連接起來(lái)的的。現(xiàn)在的事情就是要先把他們實(shí)現(xiàn)好,我們注意到Service有一個(gè)Initialize函數(shù),這個(gè)函數(shù)通過(guò)創(chuàng)建一個(gè)生成的RoaTalkCallbackProxy類然后賦值給FCallback變量,從而達(dá)到讓Server獲得那么多Callback的目的。但是現(xiàn)在服務(wù)器還沒(méi)啟動(dòng),因此先留空。FCallback設(shè)置成NULL。等到代碼寫(xiě)完了之后(見(jiàn)下文),我們需要注冊(cè)它:

                下面的VL_METHOD_PARAMETER并不是必需的,只是不寫(xiě)的話,生成的客戶端的代碼里面類的參數(shù)會(huì)變成_0,_1這樣子的東西,不好看。
             1 /*********************************************************************************************************
             2 注冊(cè)
             3 *********************************************************************************************************/
             4 
             5 VL_BEGIN_INSPECTOR_DECLARATION
             6 
             7     VL_BEGIN_BASE_CLASS(RoaTalkUser)
             8         VL_ADD_CLASS_MEMBER(Name)
             9     VL_END_CLASS(RoaTalkUser)
            10 
            11     VL_BEGIN_CALLBACK(RoaTalkCallback)
            12         VL_ADD_CLASS_METHOD(Say)
            13         VL_METHOD_PARAMETER(User)
            14         VL_METHOD_PARAMETER(Message)
            15 
            16         VL_ADD_CLASS_METHOD(Login)
            17         VL_METHOD_PARAMETER(User)
            18 
            19         VL_ADD_CLASS_METHOD(Logout)
            20         VL_METHOD_PARAMETER(User)
            21 
            22         VL_ADD_CLASS_METHOD(Rename)
            23         VL_METHOD_PARAMETER(OldName)
            24         VL_METHOD_PARAMETER(User)
            25     VL_END_CLASS(RoaTalkCallback)
            26 
            27     VL_BEGIN_DUAL_SERVICE(RoaTalkService,RoaTalkCallback)
            28         VL_ADD_CLASS_METHOD(GetCurrentName)
            29 
            30         VL_ADD_CLASS_METHOD(SetCurrentName)
            31         VL_METHOD_PARAMETER(Name)
            32 
            33         VL_ADD_CLASS_METHOD(Say)
            34         VL_METHOD_PARAMETER(Message)
            35 
            36         VL_ADD_CLASS_METHOD(GetUsers)
            37     VL_END_CLASS(RoaTalkService)
            38 
            39     VL_EXTERN_INSPECTOR_MANAGER(RoaTalk)
            40 
            41 VL_END_INSPECTOR_DECLARATION

                至此服務(wù)器就完成了。我們通過(guò)main函數(shù)來(lái)啟動(dòng)這個(gè)服務(wù)器:
             1 #include "..\..\..\..\VL++\Library\Platform\VL_Console.h"
             2 #include "RoaTalk.h"
             3 
             4 using namespace vl;
             5 using namespace vl::platform;
             6 
             7 void PrintNotify(VUnicodeString Message)
             8 {
             9     GetConsole()->WriteLine(L"NOTIFY> "+Message);
            10 }
            11 
            12 void vlmain()
            13 {
            14     GetConsole()->SetTitle(L"Vczh RoaTalk Server v1.0");
            15     GetConsole()->SetTestMemoryLeaks(true);
            16     GetConsole()->SetPauseOnExit(false);
            17 
            18     GetConsole()->WriteLine(L"Welcome to Vczh RoaTalk Server v1.0.");
            19     CreateRoaTalkServer();
            20     VL_ObjectServer Server(VL_GET_INSPECTOR_MANAGER(RoaTalk),8080,8081,L"RoaTalk");
            21     Server.Start();
            22     PrintNotify(L"Server started.");
            23     GetConsole()->WaitForEnter();
            24     Server.Stop();
            25     DestroyRoaTalkServer();
            26 }

                接下來(lái)要生成代碼了。我們看到main函數(shù)提供的HTTP端口是8080,而TCP端口是8081,服務(wù)名是RoaTalk。所以首先運(yùn)行這個(gè)程序,然后打開(kāi)IE并輸入http://localhost:8080/RoaTalk/index.htm,然后就可以看到下面的東西了:

                首先下載“服務(wù)器端回調(diào)代理.h/.cpp”到服務(wù)器工程,然后創(chuàng)建一個(gè)客戶端并下載“客戶端.h/cpp”。現(xiàn)在我們先看看服務(wù)器端需要做些什么事情。

                首先下載下來(lái)的RoaTalk_Callback.h需要手動(dòng)添加一行#include "RoaTalk.h"。這個(gè)RoaTalk.h文件就是上文展示的那些聲明所在的文件。然后就可以在RoaTalkService::Initialize()函數(shù)里面添加下面的內(nèi)容了:
            1 void RoaTalkService::Initialize()
            2 {
            3     FCallback=CreateCallbackObject<RoaTalkCallbackProxy>();
            4 }

                 到此為止,服務(wù)器端就做好了。現(xiàn)在客戶端有了客戶端.h/cpp(生成的文件名是RoaTalk.h/cpp,跟服務(wù)名相同,并不是一定要跟服務(wù)器那個(gè)文件的名字一致)之后,就可以寫(xiě)一個(gè)Win32程序來(lái)調(diào)用它了。我們可以在客戶端調(diào)用RoaTalkService類,但是需要實(shí)現(xiàn)RoaTalkCallback才能成功創(chuàng)建Service:
              1 #include "..\..\..\..\VL++\Library\Windows\VL_WinGUI.h"
              2 #include "RoaTalk.h"
              3 
              4 using namespace vl;
              5 using namespace vl::windows;
              6 using namespace vl::windows::placement;
              7 
              8 class RoaForm : public VL_WinForm , protected RoaTalkCallbackInterface
              9 {
             10 protected:
             11     class PrintMessageCommand : public VL_Base , public IVL_WinCommand
             12     {
             13     protected:
             14         RoaForm*                    FForm;
             15         VUnicodeString                FMessage;
             16     public:
             17         PrintMessageCommand(RoaForm* Form , VUnicodeString Message)
             18         {
             19             FForm=Form;
             20             FMessage=Message;
             21         }
             22 
             23         void Execute()
             24         {
             25             FForm->FEditTalking->SetText(FForm->FEditTalking->GetText()+FMessage+L"\r\n");
             26             FForm->FEditTalking->Select(FForm->FEditTalking->GetText().Length(),0);
             27             FForm->FEditTalking->ScrollToCaret();
             28         }
             29     };
             30 protected:
             31     VL_WinEdit*                        FEditName;
             32     VL_WinButton*                    FButtonLogin;
             33     VL_WinEdit*                        FEditTalking;
             34     VL_WinEdit*                        FEditMessage;
             35     VL_WinButton*                    FButtonSend;
             36 
             37     VL_AutoPtr<RoaTalkService>        FRoaTalkService;
             38 
             39     void UpdateStatus()
             40     {
             41         if(FRoaTalkService)
             42         {
             43             FEditName->SetEnabled(true);
             44             FButtonLogin->SetText(L"Rename");
             45             FEditMessage->SetEnabled(true);
             46             FButtonSend->SetEnabled(true);
             47         }
             48         else
             49         {
             50             FEditName->SetEnabled(false);
             51             FButtonLogin->SetText(L"Log In");
             52             FEditMessage->SetEnabled(true);
             53             FButtonSend->SetEnabled(false);
             54         }
             55     }
             56 
             57     void CreateService()
             58     {
             59         if(!FRoaTalkService)
             60         {
             61             try
             62             {
             63                 FRoaTalkService=new RoaTalkService(this);
             64                 FEditName->SetText(FRoaTalkService->GetCurrentName());
             65                 PrintMessage(L"==========CURRENT USERS==========");
             66                 VL_AutoPtr<VL_List<VL_AutoPtr<RoaTalkUser> , false , RoaTalkUser*>> Users=FRoaTalkService->GetUsers();
             67                 for(VInt i=0;i<Users->GetCount();i++)
             68                 {
             69                     PrintMessage(VUnicodeString(i+1)+L" : "+(*Users.Object())[i]->Name);
             70                 }
             71                 PrintMessage(L"=================================");
             72             }
             73             catch(const VL_ObjectError& e)
             74             {
             75                 ShowMessage(this,e.Message,GetText());
             76             }
             77         }
             78         UpdateStatus();
             79     }
             80 
             81     void DestroyService()
             82     {
             83         try
             84         {
             85             FRoaTalkService=0;
             86         }
             87         catch(const VL_ObjectError&)
             88         {
             89         }
             90         UpdateStatus();
             91     }
             92 
             93     void PrintMessage(VUnicodeString Message)
             94     {
             95         GetApplication()->PerformCommandLater(new PrintMessageCommand(this,Message));
             96     }
             97 
             98     void FButtonLoginClick(VL_Base* Sender)
             99     {
            100         if(FRoaTalkService)
            101         {
            102             try
            103             {
            104                 if(!FRoaTalkService->SetCurrentName(FEditName->GetText()))
            105                 {
            106                     FEditName->SetText(FRoaTalkService->GetCurrentName());
            107                 }
            108             }
            109             catch(const VL_ObjectError& e)
            110             {
            111                 ShowMessage(this,e.Message,GetText());
            112                 DestroyService();
            113             }
            114         }
            115         else
            116         {
            117             CreateService();
            118         }
            119     }
            120 
            121     void FButtonSendClick(VL_Base* Sender)
            122     {
            123         if(FRoaTalkService)
            124         {
            125             try
            126             {
            127                 FRoaTalkService->Say(FEditMessage->GetText());
            128                 PrintMessage(FRoaTalkService->GetCurrentName()+L""+FEditMessage->GetText());
            129                 FEditMessage->SetText(L"");
            130             }
            131             catch(const VL_ObjectError& e)
            132             {
            133                 ShowMessage(this,e.Message,GetText());
            134                 DestroyService();
            135             }
            136         }
            137     }
            138 
            139     void FEditMessageChar(VL_Base* Sender , VWChar& Char)
            140     {
            141         if(Char==L'\r')
            142         {
            143             FButtonSendClick(FButtonSend);
            144             Char=0;
            145         }
            146     }
            147 
            148     void FormClose(VL_Base* Sender)
            149     {
            150         DestroyService();
            151     }
            152 
            153     void Login(VL_AutoPtr<RoaTalkUser> User)
            154     {
            155         PrintMessage(L"*"+User->Name+L" logged in*");
            156     }
            157 
            158     void Logout(VL_AutoPtr<RoaTalkUser> User)
            159     {
            160         PrintMessage(L"*"+User->Name+L" logged out*");
            161     }
            162 
            163     void Rename(VUnicodeString OldName , VL_AutoPtr<RoaTalkUser> User)
            164     {
            165         PrintMessage(L"*"+OldName+L" renamed to "+User->Name+L"*");
            166     }
            167 
            168     void Say(VL_AutoPtr<RoaTalkUser> User , VUnicodeString Message)
            169     {
            170         PrintMessage(User->Name+L""+Message);
            171     }
            172 public:
            173     RoaForm():VL_WinForm(true)
            174     {
            175         FEditName=new VL_WinEdit(this,false);
            176         FButtonLogin=new VL_WinButton(this);
            177         FButtonLogin->SetText(L"Log In");
            178         FButtonLogin->OnClick.Bind(this,&RoaForm::FButtonLoginClick);
            179         FEditTalking=new VL_WinEdit(this,true);
            180         FEditTalking->SetVScroll(true);
            181         FEditTalking->SetHScroll(true);
            182         FEditTalking->SetReadonly(true);
            183         FEditMessage=new VL_WinEdit(this,false);
            184         FEditMessage->OnChar.Bind(this,&RoaForm::FEditMessageChar);
            185         FButtonSend=new VL_WinButton(this);
            186         FButtonSend->SetText(L"Send");
            187         FButtonSend->OnClick.Bind(this,&RoaForm::FButtonSendClick);
            188 
            189         OnClose.Bind(this,&RoaForm::FormClose);
            190 
            191         ApplyPlacement(
            192             pHorzFix2(10,10,
            193                 pHorzFix1(0,10,
            194                     pVertFix2(0,10,
            195                         pControl(FEditName),
            196                         pControl(FButtonLogin,80,25)
            197                         ),
            198                     pControl(FEditTalking,280,310)
            199                     ),
            200                 pVertFix2(0,10,
            201                     pControl(FEditMessage),
            202                     pControl(FButtonSend,80,25)
            203                     )
            204                 )
            205             );
            206 
            207         SetClientWidth(300);
            208         SetClientHeight(400);
            209         SetText(L"Vczh RoaTalk Client v1.0");
            210         UpdateStatus();
            211     }
            212 };
            213 
            214 void main()
            215 {
            216     RoaForm* Form=new RoaForm;
            217     Form->MoveCenter();
            218     Form->Show();
            219     GetApplication()->Run();
            220 }

                至此客戶端就完成了。下面是服務(wù)器端所有代碼,最后附上截圖。這個(gè)截圖是我的電腦上運(yùn)行服務(wù)器和一個(gè)客戶端,然后叫了另一個(gè)人在其他地方打開(kāi)我的客戶端,鏈接我的服務(wù)器,最后我這邊顯示的內(nèi)容:

                服務(wù)器端RoaTalk.h是服務(wù)的聲明:
              1 #ifndef VCZH_ROATALK_SERVICE_PROVIDER
              2 #define VCZH_ROATALK_SERVICE_PROVIDER
              3 
              4 #include "..\..\..\..\VL++\Library\Data\Inspector\VL_ObjectServer.h"
              5 
              6 using namespace vl;
              7 using namespace vl::inspector;
              8 
              9 class RoaTalkUser;
             10 class RoaTalkCallback;
             11 class RoaTalkService;
             12 
             13 /*********************************************************************************************************
             14 服務(wù)
             15 *********************************************************************************************************/
             16 
             17 class RoaTalkUser : public VL_Base
             18 {
             19 public:
             20     typedef VL_AutoPtr<RoaTalkUser>                    Ptr;
             21     typedef VL_List<Ptr , false , RoaTalkUser*>        List;
             22     typedef VL_ListedMap<VUnicodeString , Ptr>        StringMap;
             23 
             24     VUnicodeString                    Name;
             25     RoaTalkService*                    Owner;
             26 };
             27 
             28 class RoaTalkCallback : public VL_ObjectCallback
             29 {
             30 public:
             31     virtual void                    Say(RoaTalkUser::Ptr User , VUnicodeString Message);
             32     virtual void                    Login(RoaTalkUser::Ptr User);
             33     virtual void                    Logout(RoaTalkUser::Ptr User);
             34     virtual void                    Rename(VUnicodeString OldName , RoaTalkUser::Ptr User);
             35 };
             36 
             37 class RoaTalkService : public VL_ObjectService
             38 {
             39 protected:
             40     VUnicodeString                    FName;
             41     RoaTalkCallback*                FCallback;
             42 
             43     void                            Initialize();
             44 public:
             45     typedef VL_List<RoaTalkService* , true>            List;
             46 
             47     RoaTalkService();
             48     ~RoaTalkService();
             49 
             50     RoaTalkCallback*                GetCallback();
             51 
             52     VUnicodeString                    GetCurrentName();
             53     VBool                            SetCurrentName(VUnicodeString Name);
             54     void                            Say(VUnicodeString Message);
             55     VL_AutoPtr<RoaTalkUser::List>    GetUsers();
             56 };
             57 
             58 class RoaTalkServer : public VL_Base
             59 {
             60 protected:
             61     RoaTalkUser::StringMap            FUsers;
             62     VL_SynCriticalSection            FServerLock;
             63 public:
             64     RoaTalkServer();
             65     ~RoaTalkServer();
             66 
             67     VBool                            CreateUser(VUnicodeString Name , RoaTalkService* Service);
             68     VBool                            DestroyUser(VUnicodeString Name);
             69     VBool                            RenameUser(VUnicodeString OldName , VUnicodeString NewName);
             70     VL_AutoPtr<RoaTalkUser::List>    GetUsers();
             71     VBool                            Say(VUnicodeString Name , VUnicodeString Message);
             72 };
             73 
             74 extern void                            CreateRoaTalkServer();
             75 extern void                            DestroyRoaTalkServer();
             76 extern RoaTalkServer*                GetRoaTalkServer();
             77 
             78 /*********************************************************************************************************
             79 注冊(cè)
             80 *********************************************************************************************************/
             81 
             82 VL_BEGIN_INSPECTOR_DECLARATION
             83 
             84     VL_BEGIN_BASE_CLASS(RoaTalkUser)
             85         VL_ADD_CLASS_MEMBER(Name)
             86     VL_END_CLASS(RoaTalkUser)
             87 
             88     VL_BEGIN_CALLBACK(RoaTalkCallback)
             89         VL_ADD_CLASS_METHOD(Say)
             90         VL_METHOD_PARAMETER(User)
             91         VL_METHOD_PARAMETER(Message)
             92 
             93         VL_ADD_CLASS_METHOD(Login)
             94         VL_METHOD_PARAMETER(User)
             95 
             96         VL_ADD_CLASS_METHOD(Logout)
             97         VL_METHOD_PARAMETER(User)
             98 
             99         VL_ADD_CLASS_METHOD(Rename)
            100         VL_METHOD_PARAMETER(OldName)
            101         VL_METHOD_PARAMETER(User)
            102     VL_END_CLASS(RoaTalkCallback)
            103 
            104     VL_BEGIN_DUAL_SERVICE(RoaTalkService,RoaTalkCallback)
            105         VL_ADD_CLASS_METHOD(GetCurrentName)
            106 
            107         VL_ADD_CLASS_METHOD(SetCurrentName)
            108         VL_METHOD_PARAMETER(Name)
            109 
            110         VL_ADD_CLASS_METHOD(Say)
            111         VL_METHOD_PARAMETER(Message)
            112 
            113         VL_ADD_CLASS_METHOD(GetUsers)
            114     VL_END_CLASS(RoaTalkService)
            115 
            116     VL_EXTERN_INSPECTOR_MANAGER(RoaTalk)
            117 
            118 VL_END_INSPECTOR_DECLARATION
            119 
            120 #endif

                然后是它的實(shí)現(xiàn):
              1 #include "RoaTalk.h"
              2 #include "RoaTalk_Callback.h"
              3 
              4 extern void PrintNotify(VUnicodeString Message);
              5 
              6 /*********************************************************************************************************
              7 RoaTalkCallback
              8 *********************************************************************************************************/
              9 
             10 void RoaTalkCallback::Say(RoaTalkUser::Ptr User , VUnicodeString Message)
             11 {
             12 }
             13 
             14 void RoaTalkCallback::Login(RoaTalkUser::Ptr User)
             15 {
             16 }
             17 
             18 void RoaTalkCallback::Logout(RoaTalkUser::Ptr User)
             19 {
             20 }
             21 
             22 void RoaTalkCallback::Rename(VUnicodeString OldName , RoaTalkUser::Ptr User)
             23 {
             24 }
             25 
             26 /*********************************************************************************************************
             27 RoaTalkService
             28 *********************************************************************************************************/
             29 
             30 void RoaTalkService::Initialize()
             31 {
             32     FCallback=CreateCallbackObject<RoaTalkCallbackProxy>();
             33 }
             34 
             35 RoaTalkService::RoaTalkService()
             36 {
             37     FCallback=0;
             38     VInt i=1;
             39     while(true)
             40     {
             41         VUnicodeString Name=L"Guest "+VUnicodeString(i++);
             42         if(GetRoaTalkServer()->CreateUser(Name,this))
             43         {
             44             FName=Name;
             45             break;
             46         }
             47     }
             48 }
             49 
             50 RoaTalkService::~RoaTalkService()
             51 {
             52     GetRoaTalkServer()->DestroyUser(FName);
             53     delete FCallback;
             54 }
             55 
             56 RoaTalkCallback* RoaTalkService::GetCallback()
             57 {
             58     return FCallback;
             59 }
             60 
             61 VUnicodeString RoaTalkService::GetCurrentName()
             62 {
             63     return FName;
             64 }
             65 
             66 VBool RoaTalkService::SetCurrentName(VUnicodeString Name)
             67 {
             68     if(GetRoaTalkServer()->RenameUser(FName,Name))
             69     {
             70         FName=Name;
             71         return true;
             72     }
             73     else
             74     {
             75         return false;
             76     }
             77 }
             78 
             79 void RoaTalkService::Say(VUnicodeString Message)
             80 {
             81     GetRoaTalkServer()->Say(FName,Message);
             82 }
             83 
             84 VL_AutoPtr<RoaTalkUser::List> RoaTalkService::GetUsers()
             85 {
             86     return GetRoaTalkServer()->GetUsers();
             87 }
             88 
             89 /*********************************************************************************************************
             90 RoaTalkServer
             91 *********************************************************************************************************/
             92 
             93 RoaTalkServer::RoaTalkServer()
             94 {
             95 }
             96 
             97 RoaTalkServer::~RoaTalkServer()
             98 {
             99 }
            100 
            101 VBool RoaTalkServer::CreateUser(VUnicodeString Name , RoaTalkService* Service)
            102 {
            103     VBool Result=false;
            104     FServerLock.Enter();
            105     if(!FUsers.Exists(Name))
            106     {
            107         VL_AutoPtr<RoaTalkUser> Talker=new RoaTalkUser;
            108         Talker->Name=Name;
            109         Talker->Owner=Service;
            110         FUsers.Add(Name,Talker);
            111         Result=true;
            112 
            113         for(VInt i=0;i<FUsers.KeyCount();i++)
            114         {
            115             if(FUsers.KeyOfIndex(i)!=Name)
            116             {
            117                 try
            118                 {
            119                     FUsers.ValueOfIndex(i)->Owner->GetCallback()->Login(Talker);
            120                 }
            121                 catch()
            122                 {
            123                 }
            124             }
            125         }
            126 
            127         PrintNotify(Name+L" logged in.");
            128     }
            129     FServerLock.Leave();
            130     return Result;
            131 }
            132 
            133 VBool RoaTalkServer::DestroyUser(VUnicodeString Name)
            134 {
            135     VBool Result=false;
            136     FServerLock.Enter();
            137     if(FUsers.Exists(Name))
            138     {
            139         RoaTalkUser::Ptr Talker=FUsers[Name];
            140         FUsers.Delete(Name);
            141         Result=true;
            142 
            143         for(VInt i=0;i<FUsers.KeyCount();i++)
            144         {
            145             try
            146             {
            147                 FUsers.ValueOfIndex(i)->Owner->GetCallback()->Logout(Talker);
            148             }
            149             catch()
            150             {
            151             }
            152         }
            153 
            154         PrintNotify(Name+L" logged out.");
            155     }
            156     FServerLock.Leave();
            157     return Result;
            158 }
            159 
            160 VBool RoaTalkServer::RenameUser(VUnicodeString OldName , VUnicodeString NewName)
            161 {
            162     VBool Result=false;
            163     FServerLock.Enter();
            164     if(FUsers.Exists(OldName) && !FUsers.Exists(NewName))
            165     {
            166         RoaTalkUser::Ptr Talker=FUsers[OldName];
            167         FUsers.Delete(OldName);
            168         Talker->Name=NewName;
            169         FUsers.Add(NewName,Talker);
            170         Result=true;
            171 
            172         for(VInt i=0;i<FUsers.KeyCount();i++)
            173         {
            174             if(FUsers.KeyOfIndex(i)!=NewName)
            175             {
            176                 try
            177                 {
            178                     FUsers.ValueOfIndex(i)->Owner->GetCallback()->Rename(OldName,Talker);
            179                 }
            180                 catch()
            181                 {
            182                 }
            183             }
            184         }
            185 
            186         PrintNotify(OldName+L" renamed to "+NewName+L".");
            187     }
            188     FServerLock.Leave();
            189     return Result;
            190 }
            191 
            192 VL_AutoPtr<RoaTalkUser::List> RoaTalkServer::GetUsers()
            193 {
            194     RoaTalkUser::List* Result=new RoaTalkUser::List();
            195     FServerLock.Enter();
            196     for(VInt i=0;i<FUsers.KeyCount();i++)
            197     {
            198         Result->Add(FUsers.ValueOfIndex(i));
            199     }
            200     FServerLock.Leave();
            201     return Result;
            202 }
            203 
            204 VBool RoaTalkServer::Say(VUnicodeString Name , VUnicodeString Message)
            205 {
            206     VBool Result=false;
            207     FServerLock.Enter();
            208     if(FUsers.Exists(Name))
            209     {
            210         RoaTalkUser::Ptr Talker=FUsers[Name];
            211         Result=true;
            212 
            213         for(VInt i=0;i<FUsers.KeyCount();i++)
            214         {
            215             if(FUsers.KeyOfIndex(i)!=Name)
            216             {
            217                 try
            218                 {
            219                     FUsers.ValueOfIndex(i)->Owner->GetCallback()->Say(Talker,Message);
            220                 }
            221                 catch()
            222                 {
            223                 }
            224             }
            225         }
            226 
            227         PrintNotify(Name+L" says \""+Message+L"\".");
            228     }
            229     FServerLock.Leave();
            230     return Result;
            231 }
            232 
            233 /*********************************************************************************************************
            234 工具函數(shù)
            235 *********************************************************************************************************/
            236 
            237 RoaTalkServer* GlobalServer=0;
            238 
            239 void CreateRoaTalkServer()
            240 {
            241     GlobalServer=new RoaTalkServer;
            242 }
            243 
            244 void DestroyRoaTalkServer()
            245 {
            246     delete GlobalServer;
            247     GlobalServer=0;
            248 }
            249 
            250 RoaTalkServer* GetRoaTalkServer()
            251 {
            252     return GlobalServer;
            253 }
            254 
            255 /*********************************************************************************************************
            256 注冊(cè)
            257 *********************************************************************************************************/
            258 
            259 VL_BEGIN_INSPECTOR_DECLARATION
            260 
            261     VL_BEGIN_INSPECTOR_MANAGER(RoaTalk)
            262         VL_REGISTER_SERVICE_CLASSES
            263 
            264         VL_BIND_INSPECTOR(RoaTalkUser)
            265         VL_BIND_INSPECTOR(RoaTalkCallback)
            266         VL_BIND_INSPECTOR(RoaTalkService)
            267     VL_END_INSPECTOR_MANAGER
            268 
            269 VL_END_INSPECTOR_DECLARATION

                接下來(lái)就剩下花邊Feature了。使用這個(gè)東西可以開(kāi)發(fā)一些C/S模式的程序,然后只需要將服務(wù)器和客戶端看成同一個(gè)程序,將客戶端認(rèn)為是很多個(gè)線程就行了。服務(wù)器端提供一些類給客戶端創(chuàng)建并使用,當(dāng)這些服務(wù)類要求回調(diào)的時(shí)候,客戶端只需要按照回調(diào)的接口實(shí)現(xiàn)回調(diào),然后將指針提供給服務(wù)類就行了。剩下來(lái)的鏈接啊調(diào)度啊網(wǎng)絡(luò)傳輸?shù)膯?wèn)題就全部不用管了,非常方便。
            posted on 2009-07-17 18:20 陳梓瀚(vczh) 閱讀(3653) 評(píng)論(10)  編輯 收藏 引用 所屬分類: C++

            評(píng)論:
            # re: C++遠(yuǎn)程調(diào)用類操作支持Callback Interface 2009-07-17 19:01 | 99讀書(shū)人
            不錯(cuò) 來(lái)學(xué)習(xí)了  回復(fù)  更多評(píng)論
              
            # re: C++遠(yuǎn)程調(diào)用類操作支持Callback Interface 2009-07-17 19:33 | 奮斗
            無(wú)聊  回復(fù)  更多評(píng)論
              
            # re: C++遠(yuǎn)程調(diào)用類操作支持Callback Interface 2009-07-17 23:10 | SOS
            # re: C++遠(yuǎn)程調(diào)用類操作支持Callback Interface 2009-07-18 05:00 | 彭小虎(Tigerkin)
            瓦哈哈哈哈哈哈  回復(fù)  更多評(píng)論
              
            # re: C++遠(yuǎn)程調(diào)用類操作支持Callback Interface 2009-07-18 06:27 | 空明流轉(zhuǎn)
            很好,很強(qiáng)大,很幽默。  回復(fù)  更多評(píng)論
              
            # re: C++遠(yuǎn)程調(diào)用類操作支持Callback Interface 2009-07-19 06:43 | Gohan
            真的很強(qiáng)大  回復(fù)  更多評(píng)論
              
            # re: C++遠(yuǎn)程調(diào)用類操作支持Callback Interface 2009-07-20 04:08 | 移動(dòng)12530彩鈴
            阿斯頓~哈哈!  回復(fù)  更多評(píng)論
              
            # re: C++遠(yuǎn)程調(diào)用類操作支持Callback Interface 2009-07-27 05:13 | shz
            我發(fā)現(xiàn)微軟的人都很愛(ài)說(shuō)feature這個(gè)詞……娃哈哈  回復(fù)  更多評(píng)論
              
            # re: C++遠(yuǎn)程調(diào)用類操作支持Callback Interface 2010-07-01 00:48 |
            說(shuō)實(shí)話...我真的非常討厭用宏來(lái)著...能不用盡量不用。
            看到LZ用宏來(lái)定義消息和回調(diào)的地方時(shí)...有種瞬間給澆了一盆水的感覺(jué)。  回復(fù)  更多評(píng)論
              
            # re: C++遠(yuǎn)程調(diào)用類操作支持Callback Interface 2010-07-01 01:04 | 陳梓瀚(vczh)
            @釀
            這是為了可以自動(dòng)生成client的代碼。就忍忍吧。我這做的是你寫(xiě)server的class,我的類庫(kù)幫你寫(xiě)client。不這么干怎么干,除非你人寫(xiě),或者用doxygen的那種辦法。當(dāng)然這玩意兒對(duì)我來(lái)說(shuō)已經(jīng)是過(guò)時(shí)的了,你不需要在意他。  回復(fù)  更多評(píng)論
              
            久久er99热精品一区二区| 久久久精品久久久久久| 亚洲va中文字幕无码久久| 亚洲AV无一区二区三区久久| 精品无码久久久久久尤物| 99久久国产主播综合精品 | 亚洲国产精品无码久久久蜜芽| 久久精品无码午夜福利理论片| 成人精品一区二区久久久| 久久精品国产亚洲AV蜜臀色欲| 久久亚洲AV成人无码电影| 久久无码国产| 狠狠色噜噜狠狠狠狠狠色综合久久| 久久影视国产亚洲| 久久国产精品成人影院| 久久久久噜噜噜亚洲熟女综合| 久久久久国产精品熟女影院| 亚洲精品乱码久久久久久蜜桃| 久久不射电影网| 久久久久久久波多野结衣高潮 | 久久AAAA片一区二区| 久久男人Av资源网站无码软件| 久久噜噜久久久精品66| 久久精品嫩草影院| 久久精品国产99久久无毒不卡| 久久99国产精品久久99小说| 亚洲国产天堂久久综合网站| 久久99精品久久久久久动态图| 麻豆久久久9性大片| 无码精品久久一区二区三区| 99久久精品免费国产大片| 高清免费久久午夜精品| 亚洲香蕉网久久综合影视| 久久成人小视频| 久久热这里只有精品在线观看| 久久亚洲中文字幕精品一区四| 国产免费福利体检区久久| 国内精品伊人久久久久影院对白 | 久久热这里只有精品在线观看| 久久久久亚洲AV成人网人人软件| 久久国产亚洲精品麻豆|