🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: borland.public.cppbuilder.internet.socket
4 messages
4 total messages Started by Alfred Thomas Mon, 30 Aug 2004 08:34
TCP Client/Server comms using Indy 9
#5382
Author: Alfred Thomas
Date: Mon, 30 Aug 2004 08:34
54 lines
2359 bytes
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
Re: TCP Client/Server comms using Indy 9
#5384
Author: Remy Lebeau (TeamB)
Date: Mon, 30 Aug 2004 17:16
104 lines
4305 bytes
"Alfred Thomas" <alfred@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
Re: TCP Client/Server comms using Indy 9
#5389
Author: Alfred Thomas
Date: Tue, 31 Aug 2004 06:42
32 lines
2206 bytes
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
Re: TCP Client/Server comms using Indy 9
#5391
Author: Remy Lebeau (TeamB)
Date: Tue, 31 Aug 2004 16:36
16 lines
1553 bytes
"Alfred Thomas" <alfred@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
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads