2005. január 15., szombat
Making an application a TCP/IP Client (with sample code)...
Problem/Question/Abstract:
Connecting to a TCP/IP server from a Delphi Client
Answer:
This article is a continuation of my previous article "Making an application a TCP/IP Client" intended to demonstrate how we can use the TclientSocket component in Delphi as a TCP/IP client against any TCP/IP server. The server could be written in Delphi using TserverSocket component or any piece of code that acts as a TCP/IP server. In my case, I’m interacting with a Java code acts as a TCP/IP server.
In my project, I’m just sending a bunch of bytes to that Java server and the Java server reads the bytes and doing some tasks sending a different bunch of bytes as response to the Delphi Client.
In my last article (Making an application a TCP/IP Client), I explained the problem I faced and a solution I found for that.
In this article, let me give some sample code I used in that project since some people asked me to send the source code for this socket communication by sending separate e-mails. I appreciate them for their interest. Here U Go!! Enjoy!!!
My project uses nearly nine forms and all the forms need to interact with the Java server at least once. So I added a DataModule and put a TClientSocket Component there:
The following is the code for that:
unit DataMod;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ScktComp, OleServer;
type
TdmDataModule = class(TDataModule)
csClientSocket: TClientSocket;
procedure csClientSocketError(Sender: TObject; Socket: TCustomWinSocket;
ErrorEvent: TErrorEvent; var ErrorCode: Integer);
procedure csClientSocketRead(Sender: TObject;
Socket: TCustomWinSocket);
procedure DataModuleDestroy(Sender: TObject);
private
{ Private declarations }
pub
lic
FWaiting: boolean;
{ Public declarations }
end;
var
dmDataModule: TdmDataModule;
implementation
{$R *.DFM}
procedure TdmDataModule.csClientSocketRead(Sender: TObject;
Socket: TCustomWinSocket);
//Reading data back from server thro socket
var
Buffer: array[0..4095] of char;
BytesReceived: integer;
MemoryStream: TMemoryStream;
begin
while FWaiting do
begin
MemoryStream := TMemoryStream.Create;
try
//This time delay depends on the network traffic and also you can put the
//time delay between reads
//I've just put some 200 milliseconds for my application before it
//starts reading from the server.
Sleep(200);
while True do
begin
BytesReceived := Socket.ReceiveBuf(Buffer, SizeOf(Buffer));
if (BytesReceived <= 0) then
Break
else
begin
MemoryStream.Write(Buffer, BytesReceived);
end;
end;
FWaiting := False;
MemoryStream.Position := 0;
//XMLResponse is a global stringlist i'm using in my application to convert
//the bytes received into string
//You can use other ways to get the contents of a memorystream
XMLResponse.LoadFromStream(MemoryStream);
finally
MemoryStream.Free;
end;
end;
end;
procedure TdmDataModule.csClientSocketError(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
var ErrorCode: Integer);
{Whenever you get a specific type of error while running the client you will be given a messagedlg showing that the error has occured; at that time you have to check whether the server is running correctly or not and if needed make the server run properly and then say OK.
Then csClientSocket.Open will try to reconnect to the server. So at this time if some transaction is in the middle you have to send the same stuff again after reconnecting.}
begin
case ErrorEvent of
eeGeneral:
begin
if MessageDlg('Error Connecting to Java server! ' + #13 +
'Check the server status and try again!!', mtInformation, [mbOk], 0) = mrOk
then
csClientSocket.Open
end;
eeConnect:
begin
if MessageDlg('Error Connecting to Java server? ' + #13 +
'Check the server status and try again!!', mtInformation, [mbOk], 0) = mrOk
then
csClientSocket.Open
end;
eeSend:
begin
if MessageDlg('Error Connecting to Java server? ' + #13 +
'Check the server status and try again!!', mtInformation, [mbOk], 0) = mrOk
then
csClientSocket.Open
end;
eeReceive:
begin
if MessageDlg('Error Connecting to Java server? ' + #13 +
'Check the server status and try again!!', mtInformation, [mbOk], 0) = mrOk
then
csClientSocket.Open
end;
eeAccept:
begin
if MessageDlg('Error Connecting to Java server? ' + #13 +
'Check the server status and try again!!', mtInformation, [mbOk], 0) = mrOk
then
csClientSocket.Open
end;
end;
end;
procedure TdmDataModule.DataModuleDestroy(Sender: TObject);
begin
//Closing the socket connection
csClientSocket.Close;
end;
end.
Once you are done with the datamodule, you can include this datamodule in units wherever you need to interact with the server thereby you can avoid writing code to read data back from the server in various places of the project.
You can set the Host/Address and Port Number of the server to communicate at runtime through the runtime parameters.(I assume Delphi people aware of that runtime parameters)
Then in the project's main form's formcreate event; write the following code to connect to the server. i.e setting the IP address and Port Number of the server in the TClientSocket component and set Active to true.
//Connecting to the Java server on a particular port
try
with dmDataModule.csClientSocket do
begin
if Active then
Active := False;
//Getting the Address or Host Name of the server through the runtime parameters
Host := ParamStr(1);
//Getting the Port Number of the server at which the server listens through the runtime parameters
Port := StrToInt(ParamStr(2));
//Making the connection active
Active := True;
end;
except on ESocketError do
begin
MessageDlg('Unable to Connect to Java Server ' + #13 + 'Please Try Again!',
mtInformation, [mbOk], 0);
exit;
end;
end;
Once you are connected to the server, you can use either the TClientSocket's sendtext or sendstream method to send the data to the server.
for example:
procedure Send;
begin
//Checking whether the socket connection is ready or not
//If not , the error handling part of the TClientSocket will be activated
if csClientSocket.Active then
begin
//Sending the text through the socket connection
csClientSocket.Socket.SendText('The string to send');
//Setting a flag to wait until the server sends the response back
dmDataModule.FWaiting := True;
while dmDataModule.FWaiting then
Application.ProcessMessages;
end;
end;
Feliratkozás:
Megjegyzések küldése (Atom)
Nincsenek megjegyzések:
Megjegyzés küldése