Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

TCP Client/Server comms using Indy 9

721 views
Skip to first unread message

Alfred Thomas

unread,
Aug 30, 2004, 4:34:07 AM8/30/04
to

Hi All

I need to write an application using Indy's TIdTCPClient and TIdTCPServer. All I need is for the server to accept a connection and receive a text string, and the client to make a connection and send a text string out. Im having great difficulties with indefinate time-outs, exceptions etc.
My code is as follows:

In my TIdTCPServer->OnExecute:
char * Buffer = NULL;
TMemoryStream * pStrm = NULL;

try
{
AThread->Connection->ReadFromStack();
pStrm = AThread->Connection->InputBuffer;
if(pStrm->Size > 0)
{
Buffer = new char[pStrm->Size + 1];
ZeroMemory(Buffer,pStrm->Size + 1);
pStrm->Position = 0;
pStrm->Read(Buffer, pStrm->Size);
pStrm->Clear();
RequestEngine->RunQuery("X1001",AnsiString(Buffer));
}
}
catch(Exception &E)
{
ShowMessage(E.Message);
}


And on a Timer event the TIdTCPClient read:
try
{
IdTCPClient->ReadFromStack();
TMemoryStream *pStrm = IdTCPClient->InputBuffer;
if(pStrm->Size > 0 )
{
Buffer = new char[pStrm->Size + 1];
ZeroMemory(Buffer,pStrm->Size + 1);
pStrm->Position = 0;
pStrm->Read(Buffer, pStrm->Size);
pStrm->Clear();
ShowMessage("Client: " + AnsiString(Buffer));
}
}
catch(Exception &E)
{
ShowMessage(E.Message);
}

I have seen other demos where ReadLn is used and I have tried that, with no success. Can anyone please tell me what the best way for reading data from client and server TCP connections is

Regards
Alfred Thomas

Remy Lebeau (TeamB)

unread,
Aug 30, 2004, 1:16:47 PM8/30/04
to

"Alfred Thomas" <alf...@fischerint.co.za> wrote in message
news:4132e67f$1...@newsgroups.borland.com...

> I need to write an application using Indy's TIdTCPClient and TIdTCPServer.
> All I need is for the server to accept a connection and receive a text
string,
> and the client to make a connection and send a text string out.

That is very simple to do. Just have the server call the connection's
ReadLn() method in the OnExecute event, and the client call its WriteLn()
method after connecting to the server. For example:

--- server ---

void __fastcall TForm1::IdTCPServer1Execute(TIdPeerThread *AThread)
{
AnsiString Buffer = AThread->Connection->ReadLn(LF,
IdTimeoutDefault, -1);
RequestEngine->RunQuery("X1001", Buffer);
AThread->Connection->WriteLn("Some Response String Here");
}


--- client ---

// set up the client as needed...
IdTCPClient1->Connect(5000);
//...
IdTCPClient1->WriteLn("Some Query String Here");
AnsiString Response = IdTCPClient1->ReadLn(LF, IdTimeoutDefault, -1);
// use Response as needed ...
IdTCPClient1->Disconnect();


Alternatively:

--- server ---

void __fastcall TForm1::IdTCPServer1Execute(TIdPeerThread *AThread)
{
AnsiString Buffer = AThread->Connection->CurrentReadBuffer();
RequestEngine->RunQuery("X1001", Buffer);
AThread->Connection->WriteLn("Some Response String Here");
}


--- client ---

// set up the client as needed...
IdTCPClient1->Connect(5000);
//...
IdTCPClient1->Write("Some Query String Here");
AnsiString Response = IdTCPClient1->CurrentReadBuffer();
// use Response as needed ...
IdTCPClient1->Disconnect();


Alternatively:

--- server ---

void __fastcall TForm1::IdTCPServer1Execute(TIdPeerThread *AThread)
{
int length = AThread->Connection->ReadInteger(true);
AnsiString Buffer = AThread->Connection->ReadString(length);
RequestEngine->RunQuery("X1001", Buffer);
AnsiString Response = "Some Response String Here";
AThread->Connection->WriteInteger(Response.Length(), true);
AThread->Connection->Write(Response);
}


--- client ---

// set up the client as needed...
IdTCPClient1->Connect(5000);
//...
AnsiString Query = "Some Query String Here";
IdTCPClient1->WriteInteger(Query.Length(), true);
IdTCPClient1->Write(Query);
int length = IdTCPClient1->ReadInteger(true);
AnsiString Response = IdTCPClient1->ReadString(length);
// use Response as needed ...
IdTCPClient1->Disconnect();


> Im having great difficulties with indefinate time-outs, exceptions etc.

Well, for one thing, your client is trying to read a string back from the
server, but your server code does not appear to ever actually send a string
back to the client at all. Also, you have two other problems in your server
code - 1) you are catching all exceptions and then discarding them, so the
server will never know about socket errors that occur, and 2) you are using
ShowMessage(), which is not thread-safe. The OnExecute event is triggered
in the context of a worker thread, not the main VCL thread.

> I have seen other demos where ReadLn is used and I have tried that,
> with no success.

Why not? Please be more specific.


Gambit


Alfred Thomas

unread,
Aug 31, 2004, 2:42:27 AM8/31/04
to

Hi Remy

Thanks for your help.

>>AnsiString Buffer = AThread->Connection->ReadLn(LF,IdTimeoutDefault, -1);

Tried this instead of AThread->Connection->ReadLn();
The problem was that later in the program I used AThread->Connection->Write(...) instead of WriteLn(...)

>Well, for one thing, your client is trying to read a string back from the
>server, but your server code does not appear to ever actually send a string
>back to the client at all.

This is just a small piece of testing code - In the actual code, the AThread->Connection is copied to an object and later used to send back the response.



>>Also, you have two other problems in your server
>code - 1) you are catching all exceptions and then discarding them, so the
>server will never know about socket errors that occur, and 2) you are using
>ShowMessage(), which is not thread-safe.

In the actual code I will have better exception handling than ShowMessage :)

>Why not? Please be more specific.

As I said I have used ReadLn() together with Write(). I have now changed the code as you suggested and it works perfectly.
I had to convert an existing project from TClient and TServer sockets to Indy socket because I needed to use Https components.

I really appreciate your help

Regards
Alfred

Remy Lebeau (TeamB)

unread,
Aug 31, 2004, 12:36:36 PM8/31/04
to

"Alfred Thomas" <alf...@fischerint.co.za> wrote in message
news:41341dd3$1...@newsgroups.borland.com...

> In the actual code I will have better exception handling than ShowMessage
:)

The point I was trying to make is that you should not be catching the
exceptions in the first place, or at least not discarding them, at least not
the Indy ones anyway. Let them escape the event handler back into the
server so that it knows errors have happened on the socket so that it can
then be cleaned up appropriately. Indy uses exceptions internally for
notifications and such.


Gambit


0 new messages