0% found this document useful (0 votes)
103 views

DDD

This document contains code for a TCP server application implemented using the Indy component library. It defines a server form class with methods for handling server events like connecting clients, receiving messages, and disconnecting clients. These methods are used to log connections/disconnections, broadcast messages, and maintain a count of connected clients. The server listens on a specified port for guest clients to connect.

Uploaded by

didier_o
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
103 views

DDD

This document contains code for a TCP server application implemented using the Indy component library. It defines a server form class with methods for handling server events like connecting clients, receiving messages, and disconnecting clients. These methods are used to log connections/disconnections, broadcast messages, and maintain a count of connected clients. The server listens on a specified port for guest clients to connect.

Uploaded by

didier_o
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 7

1 // *****************************************************************************

2 // File : UServer.pas
3 // Project : MicroServer.dpr
4 // Easy example of TCP Server with indy component : TidTCPSever
5 //
6 // see indy doc: http://www.indyproject.org/sockets/docs/index.en.aspx
7 //
8 //
9 // *****************************************************************************
10 unit UServer;
11
12 interface
13
14 uses
15 Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
System.Classes, Vcl.Graphics,
16 Vcl.Controls, Vcl.Forms, Vcl.Dialogs, IdContext, IdComponent, Vcl.StdCtrls,
17 IdBaseComponent, IdCustomTCPServer, IdThreadSafe, IdTCPConnection, IdYarn,
IdTCPServer, Vcl.ExtCtrls;
18
19
20 type
21 TFServer = class(TForm)
22
23 Title : TLabel;
24
25 btn_start : TButton;
26 btn_stop : TButton;
27 btn_clear : TButton;
28
29 clients_connected : TLabel;
30 Label1 : TLabel;
31 Panel1 : TPanel;
32 messagesLog : TMemo;
33
34 procedure FormCreate(Sender: TObject);
35 procedure FormShow(Sender: TObject);
36
37 procedure btn_startClick(Sender: TObject);
38 procedure btn_stopClick(Sender: TObject);
39 procedure btn_clearClick(Sender: TObject);
40
41 procedure IdTCPServerConnect(AContext: TIdContext);
42 procedure IdTCPServerDisconnect(AContext: TIdContext);
43 procedure IdTCPServerExecute(AContext: TIdContext);
44 procedure IdTCPServerStatus(ASender: TObject; const AStatus: TIdStatus;
45 const AStatusText: string);
46
47 procedure ShowNumberOfClients(p_disconnected : Boolean=False);
48
49 procedure BroadcastMessage(p_message : string);
50
51 procedure Display(p_sender, p_message : string);
52 function GetNow():String;
53
54
55 private
56 { Private declarations }
57
58 public
59 { Public declarations }
60
61 end;
62 // ...
63
64
65 // ... listening port
66 const GUEST_CLIENT_PORT = 20010;
67
68 var
69 FServer : TFServer;
70
71 // ... Id TCP Server
72 IdTCPServer : TIdTCPServer;
73
74 implementation
75
76 {$R *.dfm}
77
78 // *****************************************************************************
79 // EVENT : onCreate()
80 // ON FORM CREATE
81 // *****************************************************************************
82 procedure TFServer.FormCreate(Sender: TObject);
83 begin
84
85 // ... create idTCPServer
86 IdTCPServer := TIdTCPServer.Create(self);
87 IdTCPServer.Active := False;
88
89 // ... set properties
90 IdTCPServer.MaxConnections := 20;
91
92 // ... etc..
93
94 // ... assign a new context class (if you need)
95 // IdTCPServer.ContextClass := TYourContext;
96
97 // ... add some callback functions
98 IdTCPServer.OnConnect := IdTCPServerConnect;
99 IdTCPServer.OnDisconnect := IdTCPServerDisconnect;
100 IdTCPServer.OnExecute := IdTCPServerExecute;
101 IdTCPServer.OnStatus := IdTCPServerStatus;
102 // ... etc..
103
104 end;
105 // .............................................................................
106
107
108 // *****************************************************************************
109 // EVENT : onShow()
110 // ON FORM SHOW
111 // *****************************************************************************
112 procedure TFServer.FormShow(Sender: TObject);
113 begin
114 // ... INITIALIZE:
115
116 // ... clear message log
117 messagesLog.Lines.Clear;
118
119 // ... zero to clients connected
120 clients_connected.Caption := inttostr(0);
121
122 // ... set buttons
123 btn_start.enabled := True;
124 btn_stop.enabled := False;
125 end;
126 // .............................................................................
127
128
129 // *****************************************************************************
130 // EVENT : btn_startClick()
131 // CLICK ON START BUTTON
132 // *****************************************************************************
133 procedure TFServer.btn_startClick(Sender: TObject);
134 begin
135 // ... START SERVER:
136
137 // ... clear the Bindings property ( ... Socket Handles )
138 IdTCPServer.Bindings.Clear;
139 // ... Bindings is a property of class: TIdSocketHandles;
140
141 // ... add listening ports:
142
143 // ... add a port for connections from guest clients.
144 IdTCPServer.Bindings.Add.Port := GUEST_CLIENT_PORT;
145 // ... etc..
146
147
148 // ... ok, Active the Server!
149 IdTCPServer.Active := True;
150
151 // ... disable start button
152 btn_start.enabled := False;
153
154 // ... enable stop button
155 btn_stop.enabled := True;
156
157 // ... message log
158 Display('SERVER', 'STARTED!');
159
160 end;
161 // .............................................................................
162
163
164 // *****************************************************************************
165 // EVENT : btn_stopClick()
166 // CLICK ON STOP BUTTON
167 // *****************************************************************************
168 procedure TFServer.btn_stopClick(Sender: TObject);
169 begin
170
171 // ... before stopping the server ... send 'good bye' to all clients connected
172 BroadcastMessage('Goodbye Client ');
173
174 // ... stop server!
175 IdTCPServer.Active := False;
176
177 // ... hide stop button
178 btn_stop.enabled := False;
179
180 // ... show start button
181 btn_start.enabled := True;
182
183 // ... message log
184 Display('SERVER', 'STOPPED!');
185
186 end;
187 // .............................................................................
188
189
190 // *****************************************************************************
191 // EVENT : btn_clearClick()
192 // CLICK ON CLEAR BUTTON
193 // *****************************************************************************
194 procedure TFServer.btn_clearClick(Sender: TObject);
195 begin
196 //... clear messages log
197 MessagesLog.Lines.Clear;
198 end;
199 // .............................................................................
200
201 // .............................................................................
202 // .............................................................................
203 // .............................................................................
204
205 // *****************************************************************************
206 // EVENT : onConnect()
207 // OCCURS ANY TIME A CLIENT IS CONNECTED
208 // *****************************************************************************
209 procedure TFServer.IdTCPServerConnect(AContext: TIdContext);
210 var
211 ip : string;
212 port : Integer;
213 peerIP : string;
214 peerPort : Integer;
215
216 nClients : Integer;
217
218 msgToClient : string;
219 typeClient : string;
220
221 begin
222 // ... OnConnect is a TIdServerThreadEvent property that represents the event
223 // handler signalled when a new client connection is connected to the server.
224
225 // ... Use OnConnect to perform actions for the client after it is connected
226 // and prior to execution in the OnExecute event handler.
227
228 // ... see indy doc:
229 // http://www.indyproject.org/sockets/docs/index.en.aspx
230
231 // ... getting IP address and Port of Client that connected
232 ip := AContext.Binding.IP;
233 port := AContext.Binding.Port;
234 peerIP := AContext.Binding.PeerIP;
235 peerPort := AContext.Binding.PeerPort;
236
237 // ... message log
238 Display('SERVER', 'Client Connected!');
239 Display('SERVER', 'Port=' + IntToStr(Port)
240 + ' ' + '(PeerIP=' + PeerIP
241 + ' - ' + 'PeerPort=' + IntToStr(PeerPort) + ')'
242 );
243
244 // ... display the number of clients connected
245 ShowNumberOfClients();
246
247 // ... CLIENT CONNECTED:
248 case Port of
249 GUEST_CLIENT_PORT : begin
250 // ... GUEST CLIENTS
251 typeClient := 'GUEST';
252 end;
253 // ...
254 end;
255
256 // ... send the Welcome message to Client connected
257 msgToClient := 'Welcome ' + typeClient + ' ' + 'Client :)';
258 AContext.Connection.IOHandler.WriteLn( msgToClient );
259
260 end;
261 // .............................................................................
262
263 // *****************************************************************************
264 // EVENT : onDisconnect()
265 // OCCURS ANY TIME A CLIENT IS DISCONNECTED
266 // *****************************************************************************
267 procedure TFServer.IdTCPServerDisconnect(AContext: TIdContext);
268 var
269 ip : string;
270 port : Integer;
271 peerIP : string;
272 peerPort : Integer;
273
274 nClients : Integer;
275 begin
276
277 // ... getting IP address and Port of Client that connected
278 ip := AContext.Binding.IP;
279 port := AContext.Binding.Port;
280 peerIP := AContext.Binding.PeerIP;
281 peerPort := AContext.Binding.PeerPort;
282
283 // ... message log
284 Display('SERVER', 'Client Disconnected! Peer=' + PeerIP + ':' +
IntToStr(PeerPort));
285
286 // ... display the number of clients connected
287 ShowNumberOfClients(true);
288 end;
289 // .............................................................................
290
291
292 // *****************************************************************************
293 // EVENT : onExecute()
294 // ON EXECUTE THREAD CLIENT
295 // *****************************************************************************
296 procedure TFServer.IdTCPServerExecute(AContext: TIdContext);
297 var
298 Port : Integer;
299 PeerPort : Integer;
300 PeerIP : string;
301
302 msgFromClient : string;
303 msgToClient : string;
304 begin
305
306 // ... OnExecute is a TIdServerThreadEvents event handler used to execute
307 // the task for a client connection to the server.
308
309 // ... here you can check connection status and buffering before reading
310 // messages from client
311
312 // ... see doc:
313 // ... AContext.Connection.IOHandler.InputBufferIsEmpty
314 // ... AContext.Connection.IOHandler.CheckForDataOnSource(<milliseconds>);
315 // (milliseconds to wait for the connection to become readable)
316 // ... AContext.Connection.IOHandler.CheckForDisconnect;
317
318 // ... received a message from the client
319
320 // ... get message from client
321 msgFromClient := AContext.Connection.IOHandler.ReadLn;
322
323 // ... getting IP address, Port and PeerPort from Client that connected
324 peerIP := AContext.Binding.PeerIP;
325 peerPort := AContext.Binding.PeerPort;
326
327 // ... message log
328 Display('CLIENT', '(Peer=' + PeerIP + ':' + IntToStr(PeerPort) + ') ' +
msgFromClient);
329 // ...
330
331 // ... process message from Client
332
333 // ...
334
335 // ... send response to Client
336
337 AContext.Connection.IOHandler.WriteLn('... message sent from server :)');
338
339 end;
340 // .............................................................................
341
342
343 // *****************************************************************************
344 // EVENT : onStatus()
345 // ON STATUS CONNECTION
346 // *****************************************************************************
347 procedure TFServer.IdTCPServerStatus(ASender: TObject; const AStatus: TIdStatus;
348 const AStatusText: string);
349 begin
350 // ... OnStatus is a TIdStatusEvent property that represents the event handler
351 // triggered when the current connection state is changed...
352
353 // ... message log
354 Display('SERVER', AStatusText);
355 end;
356 // .............................................................................
357
358
359 // *****************************************************************************
360 // FUNCTION : getNow()
361 // GET MOW DATE TIME
362 // *****************************************************************************
363 function TFServer.getNow() : String;
364 begin
365 Result := FormatDateTime('yyyy-mm-dd hh:nn:ss', Now) + ': ';
366 end;
367 // .............................................................................
368
369
370 // *****************************************************************************
371 // PROCEDURE : broadcastMessage()
372 // BROADCAST A MESSAGE TO ALL CLIENTS CONNECTED
373 // *****************************************************************************
374 procedure TFServer.broadcastMessage(p_message : string);
375 var
376 tmpList : TList;
377 contexClient : TidContext;
378 nClients : Integer;
379 i : integer;
380 begin
381
382 // ... send a message to all clients connected
383
384 // ... get context Locklist
385 tmpList := IdTCPServer.Contexts.LockList;
386
387 try
388 i := 0;
389 while ( i < tmpList.Count ) do begin
390 // ... get context (thread of i-client)
391 contexClient := tmpList[i];
392
393 // ... send message to client
394 contexClient.Connection.IOHandler.WriteLn(p_message);
395 i := i + 1;
396 end;
397
398 finally
399 // ... unlock list of clients!
400 IdTCPServer.Contexts.UnlockList;
401 end;
402 end;
403 // .............................................................................
404
405 // *****************************************************************************
406 // PROCEDURE : Display()
407 // DISPLAY MESSAGE UPON SYSOUT
408 // *****************************************************************************
409 procedure TFServer.Display(p_sender : String; p_message : string);
410 begin
411 // ... DISPLAY MESSAGE
412 TThread.Queue(nil, procedure
413 begin
414 MessagesLog.Lines.Add('[' + p_sender + '] - '
415 + getNow() + ': ' + p_message);
416 end
417 );
418
419 // ... see doc..
420 // ... TThread.Queue() causes the call specified by AMethod to
421 // be asynchronously executed using the main thread, thereby avoiding
422 // multi-thread conflicts.
423 end;
424 // .............................................................................
425
426 // *****************************************************************************
427 // PROCEDURE : ShowNumberOfClients()
428 // NUMBER OF CLIENTS CONNECTD
429 // *****************************************************************************
430 procedure TFServer.ShowNumberOfClients(p_disconnected : Boolean=False);
431 var
432 nClients : integer;
433 begin
434
435 try
436 // ... get number of clients connected
437 nClients := IdTCPServer.Contexts.LockList.Count;
438 finally
439 IdTCPServer.Contexts.UnlockList;
440 end;
441
442 // ... client disconnected?
443 if p_disconnected then dec(nClients);
444
445 // ... display
446 TThread.Queue(nil, procedure
447 begin
448 clients_connected.Caption := IntToStr(nClients);
449 end
450 );
451 end;
452 // .............................................................................
453
454
455 end.

You might also like