至此客户端就完成了。下面是服务器端所有代码,最后附上截图。这个截图是我的电脑上运行服务器和一个客户端,然后叫了另一个人在其他地方打开我的客户端,链接我的服务器,最后我这边显示的内容:
服务器端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模式的程序,然后只需要将服务器和客户端看成同一个程序,将客户端认为是很多个线程就行了。服务器端提供一些类给客户端创建并使用,当这些服务类要求回调的时候,客户端只需要按照回调的接口实现回调,然后将指针提供给服务类就行了。剩下来的链接啊调度啊网络传输的问题就全部不用管了,非常方便。