🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: borland.public.cppbuilder.internet.socket
11 messages
11 total messages Started by Darlington ADIBE Thu, 17 Nov 2005 07:27
Indy TCP "Wait for Reply"
#3091
Author: Darlington ADIBE
Date: Thu, 17 Nov 2005 07:27
26 lines
2110 bytes
Hi All,

Am doing an App using the indy TCP server/Client componnet and i need an
adivce on how best to handle the situation am about the describle below.

the tcp client is in a COM object with the following methods Authenticat,
Send, etc....,
when the host  client app (exe using my COM API) calls the authenticate
method, my com obj tries to connect to a TCP Server on a remote machine, if
connected it send the uid and pwd parameter pass through authenticate to the
server msg format "#AUTHEN#xxxx#xxxx# where AUTHEN = do Authentication,
first xxxx = Username, second xxxx = password, the server check the
username/password pairs in a database, if correct it sends back #AUTHEN#OK#
if not it sends #AUTHEN#ERR#xxxxxxx# where xxxxx = reason of then Error.

The situation above i have don so far, the issue is in the client end, when
the exe call the com api Authenticate(uid, pwd), I don't want the method
(authenticate) to return untill the server send back #AUTHEN#OK# or
#AUTHEN#ERR#xxxxxx# or a RTimeout property of the COM obj is reached
RTimeout is the Rececive Time Out propety of the con obj that indicate how
long to wait before expected receive times out.

Any profession advice on how to implement this "wait for reply" issue


Darl.
Re: Indy TCP "Wait for Reply"
#3095
Author: Remy Lebeau (TeamB)
Date: Thu, 17 Nov 2005 18:08
68 lines
2862 bytes
"Darlington ADIBE" <bcb@triative.com> wrote in message
news:437c328b@newsgroups.borland.com...

> Any profession advice on how to implement this "wait for reply" issue

Indy already implements all of that for you.  Simply read from the socket
immediately after you write to it.  The reading will not return until data
is actually received, or a timeout/error occurs.  For example:

    HRESULT __stdcall TMyComObjImpl::Authenticate(BSTR uid, BSTR pwd)
    {
        try
        {
            AnsiString Cmd;
            AnsiString Response;
            AnsiString Status;

            Cmd.sprintf("#AUTHEN#%s#%s#", AnsiString(uid).c_str(),
AnsiString(pwd).c_str());

            TCPClient->Connect(5000);
            try
            {
                TCPClient->WriteLn(Cmd);
                Response = TCPClient->ReadLn(LF, IdTimeoutDefault; -1);

                Response.Delete(1,1);
                if( Fetch(Response, "#") != "AUTHEN" )
                    throw Exception("Unknown response");

                Status = Fetch(Response, "#");
                if( Status != "OK" )
                {
                    if( Status == "ERR" )
                        throw Exception("Authentication failed: " +
Fetch(Response, "#"));
                    else
                        throw Exception("Unknown response");
                }
            }
            catch(const Exception &)
            {
                TCPClient->Disconnect();
                throw;
            }
        }
        catch(const Exception &e)
        {
            return Error(e.Message, IID_IMyComObj);
        }
        return S_OK;
    }

    HRESULT __stdcall TMyComObjImpl::get_RTimeout(long *Result)
    {
        *Result = TCPClient->ReadTimeout;
        return S_OK;
    }

    HRESULT __stdcall TMyComObjImpl::set_RTimeout(long Value)
    {
        TCPClient->ReadTimeout = Value;
        return S_OK;
    }


Gambit
Re: Indy TCP "Wait for Reply"
#3098
Author: Darlington ADIBE
Date: Thu, 17 Nov 2005 18:58
79 lines
3312 bytes
Thank, looks perfect for what i needed. By the way 'Fetch' is it a BCB6
function or what?

Darl.


"Remy Lebeau (TeamB)" <no.spam@no.spam.com> wrote in message
news:437cc79a$1@newsgroups.borland.com...
>
> "Darlington ADIBE" <bcb@triative.com> wrote in message
> news:437c328b@newsgroups.borland.com...
>
> > Any profession advice on how to implement this "wait for reply" issue
>
> Indy already implements all of that for you.  Simply read from the socket
> immediately after you write to it.  The reading will not return until data
> is actually received, or a timeout/error occurs.  For example:
>
>     HRESULT __stdcall TMyComObjImpl::Authenticate(BSTR uid, BSTR pwd)
>     {
>         try
>         {
>             AnsiString Cmd;
>             AnsiString Response;
>             AnsiString Status;
>
>             Cmd.sprintf("#AUTHEN#%s#%s#", AnsiString(uid).c_str(),
> AnsiString(pwd).c_str());
>
>             TCPClient->Connect(5000);
>             try
>             {
>                 TCPClient->WriteLn(Cmd);
>                 Response = TCPClient->ReadLn(LF, IdTimeoutDefault; -1);
>
>                 Response.Delete(1,1);
>                 if( Fetch(Response, "#") != "AUTHEN" )
>                     throw Exception("Unknown response");
>
>                 Status = Fetch(Response, "#");
>                 if( Status != "OK" )
>                 {
>                     if( Status == "ERR" )
>                         throw Exception("Authentication failed: " +
> Fetch(Response, "#"));
>                     else
>                         throw Exception("Unknown response");
>                 }
>             }
>             catch(const Exception &)
>             {
>                 TCPClient->Disconnect();
>                 throw;
>             }
>         }
>         catch(const Exception &e)
>         {
>             return Error(e.Message, IID_IMyComObj);
>         }
>         return S_OK;
>     }
>
>     HRESULT __stdcall TMyComObjImpl::get_RTimeout(long *Result)
>     {
>         *Result = TCPClient->ReadTimeout;
>         return S_OK;
>     }
>
>     HRESULT __stdcall TMyComObjImpl::set_RTimeout(long Value)
>     {
>         TCPClient->ReadTimeout = Value;
>         return S_OK;
>     }
>
>
> Gambit
>
>
>
Re: Indy TCP "Wait for Reply"
#3099
Author: Remy Lebeau (TeamB)
Date: Thu, 17 Nov 2005 21:18
11 lines
1254 bytes
"Darlington ADIBE" <bcb@triative.com> wrote in message
news:437cd28f@newsgroups.borland.com...

> Thank, looks perfect for what i needed. By the way
> 'Fetch' is it a BCB6 function or what?

It is an Indy function, in the IdGlobal unit.


Gambit
Re: Indy TCP "Wait for Reply"
#3100
Author: Darlington ADIBE
Date: Thu, 17 Nov 2005 21:48
24 lines
1859 bytes
Thank again.
IdTCPClient or IdTCPServer doesn't have this property  "ReadTimeout" and how
do I change the default time as in
tcpclient->ReadLn(LF, IdTimeoutDefault); how do i make the server to LF as
line terminator and then change the default time value since ReadTimeout is
not a valid property.

Darl.

"Remy Lebeau (TeamB)" <no.spam@no.spam.com> wrote in message
news:437cf568$1@newsgroups.borland.com...
>
> "Darlington ADIBE" <bcb@triative.com> wrote in message
> news:437cd28f@newsgroups.borland.com...
>
> > Thank, looks perfect for what i needed. By the way
> > 'Fetch' is it a BCB6 function or what?
>
> It is an Indy function, in the IdGlobal unit.
>
>
> Gambit
>
>
Re: Indy TCP "Wait for Reply"
#3101
Author: Remy Lebeau (TeamB)
Date: Thu, 17 Nov 2005 21:57
15 lines
1529 bytes
"Darlington ADIBE" <bcb@triative.com> wrote in message
news:437cfa81@newsgroups.borland.com...

> IdTCPClient or IdTCPServer doesn't have this property
> "ReadTimeout"

Yes, they do.  It is a property of TIdTCPConnection in Indy 9 and of
TIdIOHandler in Indy 10.  If you don't have the property, then you must be
using the version of Indy that ships with BCB6.  That version of Indy is
VERY old and no longer supported.  You should seriously consider upgrading
to a newer version.


Gambit
Re: Indy TCP "Wait for Reply"
#3103
Author: Darlington ADIBE
Date: Fri, 18 Nov 2005 00:33
31 lines
1994 bytes
> Yes, they do.  It is a property of TIdTCPConnection in Indy 9 and of
> TIdIOHandler in Indy 10.  If you don't have the property, then you must be
> using the version of Indy that ships with BCB6.  That version of Indy is
> VERY old and no longer supported.  You should seriously consider upgrading
> to a newer version.


I have up graded to indy9.

and now my server doesn't work again i get an access voilation error in the
Execute Event


void __fastcall TForm1::tcpExecute(TIdPeerThread *AThread)
{
  AnsiString cmd;
  AnsiString request;
  do{
    request = AThread->Connection->ReadLn(LF, -2);   <---- Error is thrown
here
    cmd = Fetch(request, "#");
    if(cmd == "AUTHEN") Authenticate(AThread, request);

  } while(cmd != AnsiString("DISCONT"));
  AThread->Connection->Disconnect();
}

I still don't see any property that allow me to change the default Line
Terminatior, that of ReadTimeout I saw

Darl.
Re: Indy TCP "Wait for Reply"
#3104
Author: Remy Lebeau (TeamB)
Date: Fri, 18 Nov 2005 01:44
42 lines
2502 bytes
"Darlington ADIBE" <bcb@triative.com> wrote in message
news:437d20f2@newsgroups.borland.com...

> I have up graded to indy9.

Which build, though?

> and now my server doesn't work again i get an
> access voilation error in the Execute Event

Your code should not be looping at all.  The OnExecute event handler is
already looped internally by Indy.  Just process a single command and then
exit the handler, ie:

    void __fastcall TForm1::tcpExecute(TIdPeerThread *AThread)
    {
        AnsiString request = AThread->Connection->ReadLn(LF,
IdTimeoutDefault, -1);
        request.Delete(1, 1);
        AnsiString cmd = Fetch(request, "#");
        if( cmd == "AUTHEN" )
            Authenticate(AThread, request);
        else if( cmd == "DISCONT" )
            AThread->Connection->DisconnectSocket();
    }

You might also consider using the CommandHandler collection instead of the
OnExecute event.  The CommandHandler collection provides much automation
when it comes to parsing and processing textual commands.

> I still don't see any property that allow me to change the
> default Line Terminatior

There is no property for that.  Simply specify the desired line terminator
when calling ReadLn().  That is what its first parameter is for:

    AnsiString request =
AThread->Connection->ReadLn('YourLineDelimiterHere', IdTimeoutDefault, -1);


Gambit
Re: Indy TCP "Wait for Reply"
#3110
Author: Darlington ADIBE
Date: Fri, 18 Nov 2005 16:26
59 lines
3100 bytes
Remy thank alot,

Indy 9.0.17 was very helpful, the CommandHandler made my code very easy and
well structured, though am still to figure how to use the some other new
features

I give it Up for the Indy Team.
I hope DevStudio2006  will support Indy 10 (as in C++ )

Darl.


"Remy Lebeau (TeamB)" <no.spam@no.spam.com> wrote in message
news:437d3195$1@newsgroups.borland.com...
>
> "Darlington ADIBE" <bcb@triative.com> wrote in message
> news:437d20f2@newsgroups.borland.com...
>
> > I have up graded to indy9.
>
> Which build, though?
>
> > and now my server doesn't work again i get an
> > access voilation error in the Execute Event
>
> Your code should not be looping at all.  The OnExecute event handler is
> already looped internally by Indy.  Just process a single command and then
> exit the handler, ie:
>
>     void __fastcall TForm1::tcpExecute(TIdPeerThread *AThread)
>     {
>         AnsiString request = AThread->Connection->ReadLn(LF,
> IdTimeoutDefault, -1);
>         request.Delete(1, 1);
>         AnsiString cmd = Fetch(request, "#");
>         if( cmd == "AUTHEN" )
>             Authenticate(AThread, request);
>         else if( cmd == "DISCONT" )
>             AThread->Connection->DisconnectSocket();
>     }
>
> You might also consider using the CommandHandler collection instead of the
> OnExecute event.  The CommandHandler collection provides much automation
> when it comes to parsing and processing textual commands.
>
> > I still don't see any property that allow me to change the
> > default Line Terminatior
>
> There is no property for that.  Simply specify the desired line terminator
> when calling ReadLn().  That is what its first parameter is for:
>
>     AnsiString request =
> AThread->Connection->ReadLn('YourLineDelimiterHere',
IdTimeoutDefault, -1);
>
>
> Gambit
>
>
FYI
#3111
Author: Darlington ADIBE
Date: Fri, 18 Nov 2005 18:38
16 lines
1563 bytes
FYI:

I tried a move my core funtions into my COM Obj, which mean I had to now
manually include the nesesary header, since my COM have no Visual control.

I notict that when you #include <IdTCPClient.hpp>, i get error that alot of
variables was decleared early.
on examination i noticed that both the winsock2.h and winsock.h was include
along the IdTCPClient.hpp which is not the case if i had place the control
on the Form directly.

However i worked around it by #define _WINSOCKAPI_  just before #include
<IdTCPClient.hpp>

Am just wondering if I did some wrong along the line or if anybody have
noticed this too.
Re: FYI
#3112
Author: Remy Lebeau (TeamB)
Date: Fri, 18 Nov 2005 19:54
16 lines
1469 bytes
"Darlington ADIBE" <bcb@triative.com> wrote in message
news:437e1f49@newsgroups.borland.com...

> I notict that when you #include <IdTCPClient.hpp>, i get error
> that alot of variables was decleared early. on examination i noticed
> that both the winsock2.h and winsock.h was include along the
> IdTCPClient.hpp

That is a known issue with Indy.  It is more of a Microsoft problem than an
Indy problem, though, because winsock.h and winsock2.h are not compatible
with each other.  The VCL uses winsock.h whereas Indy uses winsock2.h
instead.


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