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

                今天展示一下如何使用這里描寫的庫實現一個簡單的聊天工具。Callback Interface是昨晚才加的,但是還有一些features沒實現,等做完了再做一個Demo,然后提供源代碼。

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

                首先我們定義這個聊天工具的接口。聊天工具登錄的時候服務器會自動分配一個名稱,用戶可以隨后更改。然后剩下的只有兩個操作:發送信息和退出登錄。我們默認程序關閉的時候退出登錄。于是可以先做一個User類,然后做一個Service類,Service調用Callback來告訴其他用戶某人發送了信息:

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

                這只是給客戶端調用的外殼。因為每一個客戶端連接的時候,系統就會創建一個RoaTalkService類,所以還需要一個全局變量來記錄所有的Service類(未來可能會提供Feature來避免這種全局變量的產生)。這個全局的服務類是需要鎖的:
             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();

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

                下面的VL_METHOD_PARAMETER并不是必需的,只是不寫的話,生成的客戶端的代碼里面類的參數會變成_0,_1這樣子的東西,不好看。
             1 /*********************************************************************************************************
             2 注冊
             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

                至此服務器就完成了。我們通過main函數來啟動這個服務器:
             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 }

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

                首先下載“服務器端回調代理.h/.cpp”到服務器工程,然后創建一個客戶端并下載“客戶端.h/cpp”。現在我們先看看服務器端需要做些什么事情。

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

                 到此為止,服務器端就做好了。現在客戶端有了客戶端.h/cpp(生成的文件名是RoaTalk.h/cpp,跟服務名相同,并不是一定要跟服務器那個文件的名字一致)之后,就可以寫一個Win32程序來調用它了。我們可以在客戶端調用RoaTalkService類,但是需要實現RoaTalkCallback才能成功創建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 }

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

                服務器端RoaTalk.h是服務的聲明:
              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 服務
             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 注冊
             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

                然后是它的實現:
              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 工具函數
            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 注冊
            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

                接下來就剩下花邊Feature了。使用這個東西可以開發一些C/S模式的程序,然后只需要將服務器和客戶端看成同一個程序,將客戶端認為是很多個線程就行了。服務器端提供一些類給客戶端創建并使用,當這些服務類要求回調的時候,客戶端只需要按照回調的接口實現回調,然后將指針提供給服務類就行了。剩下來的鏈接啊調度啊網絡傳輸的問題就全部不用管了,非常方便。
            posted on 2009-07-17 18:20 陳梓瀚(vczh) 閱讀(3652) 評論(10)  編輯 收藏 引用 所屬分類: C++

            評論:
            # re: C++遠程調用類操作支持Callback Interface 2009-07-17 19:01 | 99讀書人
            不錯 來學習了  回復  更多評論
              
            # re: C++遠程調用類操作支持Callback Interface 2009-07-17 19:33 | 奮斗
            無聊  回復  更多評論
              
            # re: C++遠程調用類操作支持Callback Interface 2009-07-17 23:10 | SOS
            拍手  回復  更多評論
              
            # re: C++遠程調用類操作支持Callback Interface 2009-07-18 05:00 | 彭小虎(Tigerkin)
            瓦哈哈哈哈哈哈  回復  更多評論
              
            # re: C++遠程調用類操作支持Callback Interface 2009-07-18 06:27 | 空明流轉
            很好,很強大,很幽默。  回復  更多評論
              
            # re: C++遠程調用類操作支持Callback Interface 2009-07-19 06:43 | Gohan
            真的很強大  回復  更多評論
              
            # re: C++遠程調用類操作支持Callback Interface 2009-07-20 04:08 | 移動12530彩鈴
            阿斯頓~哈哈!  回復  更多評論
              
            # re: C++遠程調用類操作支持Callback Interface 2009-07-27 05:13 | shz
            我發現微軟的人都很愛說feature這個詞……娃哈哈  回復  更多評論
              
            # re: C++遠程調用類操作支持Callback Interface 2010-07-01 00:48 |
            說實話...我真的非常討厭用宏來著...能不用盡量不用。
            看到LZ用宏來定義消息和回調的地方時...有種瞬間給澆了一盆水的感覺。  回復  更多評論
              
            # re: C++遠程調用類操作支持Callback Interface 2010-07-01 01:04 | 陳梓瀚(vczh)
            @釀
            這是為了可以自動生成client的代碼。就忍忍吧。我這做的是你寫server的class,我的類庫幫你寫client。不這么干怎么干,除非你人寫,或者用doxygen的那種辦法。當然這玩意兒對我來說已經是過時的了,你不需要在意他。  回復  更多評論
              
            精品久久人人妻人人做精品 | 久久不射电影网| 欧美精品一区二区精品久久| 久久久久国产精品三级网| 欧美久久久久久| 国产91色综合久久免费| 久久99国产精品久久99小说 | 久久久久免费精品国产| 伊人情人综合成人久久网小说| 麻豆成人久久精品二区三区免费| 91久久国产视频| 久久久久成人精品无码中文字幕 | 久久精品国产免费一区| 狠狠综合久久AV一区二区三区 | 久久午夜免费视频| 国产亚洲成人久久| 久久久婷婷五月亚洲97号色| 亚洲&#228;v永久无码精品天堂久久 | 亚洲综合精品香蕉久久网97 | 久久久久综合中文字幕| 99精品久久精品| 国内高清久久久久久| 久久人人爽人人爽人人片AV麻豆 | 国内精品伊人久久久久妇| 国产成人精品久久一区二区三区av | 国产成人精品综合久久久久| 欧美午夜精品久久久久久浪潮| 国产精品久久久久影院色| 欧洲成人午夜精品无码区久久| 久久人人爽人人爽人人片AV东京热 | 精品国产乱码久久久久久郑州公司| 亚洲精品无码久久久| 久久久久亚洲精品无码网址| 99久久精品这里只有精品| 久久国产精品一区二区| 国产精品久久一区二区三区| 国产成人精品综合久久久久| 久久久久久久女国产乱让韩| 亚洲香蕉网久久综合影视| 国产A三级久久精品| 香蕉久久av一区二区三区|