The example we used in the previous article is fine, but it can never be a real world application. It is not thread safe, and it does not identify all connected clients clearly enough. In this final part of the series, we will modify the application we have created in the earlier parts so that it can be used in the real world.
A Real World Client Server Application in Delphi - The Client (Page 2 of 4 )
To make our client truly thread safe we need to solve the following two problems:
Reading and processing the response from server.
Displaying that information in a thread safe manner.
Currently, to read a response from the server, the client does this:
procedureTForm1.Button1Click(Sender: TObject);
begin
IdTCPClient1.SendCmd(edit1.text);
memo1.Clear;
memo1.lines.add(idtcpclient1.Socket.ReadLn);
end;
which as we've stated earlier is not thread safe. So, to read the responses from the server we will create a thread that reads those responses. That will be its sole purpose. It will be derived from the VCL's TThread class:
class procedure AddResponse(const AResponse: String);
end;
There are two classes here, TReadResponse and TWriteResponse. TReadResponsecontains one method and a variable. The variable will hold the connection status of the client, and the execute method is used to do the actual reading:
You always override the execute method when you use the VCL's TThread class. This enables you to make it do whatever you want it to do. In our case, we want it to read the response from the server.
The TWriteResponse class is primarily responsible for writing the response that the client gets from the server to the Delphi component, which in this case is the memo component:
procedure TWriteResponse.DoSynchronize;
begin
form1. memo1.Lines.Add(FMsg);
end;
The FMsg variable is used to store the response from the server. And the DoSyncronize method is then responsible for writing that response to the memo component. The class itself is derived from the TIdSync class. TIdSync allows for synchronizations with the ability to pass parameters to the synchronized methods as well. TIdSync also allows for return values to be returned from the main thread.
Before writing the implementations of these methods, add the following to your form's variable section:
rr: TReadResponse = nil;
Your complete client code should look something like this: