Newsgroups : Borland : borland.public.delphi.internet.winsock : 2006 Mar : Re: INDY TIdTCPClient and TIdTCPServer Usage

www.cryer.info
Managed Newsgroup Archive

Re: INDY TIdTCPClient and TIdTCPServer Usage

Subject:Re: INDY TIdTCPClient and TIdTCPServer Usage
Posted by:"Remy Lebeau (TeamB)" (no.spam@no.spam.com)
Date:Mon, 20 Mar 2006 11:47:51

"Dennis" <marianndkc@home3.gvdnet.dk> wrote in message
news:441eb092$1@newsgroups.borland.com...

> I am able to connect and send one string with the SendCMD method.
> The problem is that the method fails returning because it does not accept
> the answer from the server.

That is because the server code is not writing back its response data in a
format that TIdTCPClient.SendCmd() recognizes.

> IdTCPClient1.SendCmd('Hello', 'OK');

That will not work.  For a plain TIdTCPClient, SendCmd() expects numeric
values, not strings, for the server's response code.  The only protocols
that Indy implements that use string-based response codes are POP3 and
IMAP4.  Every other protocol uses numeric values instead.

>        //RichEdit1.Lines.Add('OnExecute triggered');
>        RichEdit1.Lines.Add(lCmd);

Neither of those lines are thread-safe.  You need to use TIdSync to access
the GUI objects in a thread-safe manner.

> The client raises an exception "Reply code is not valid: OK".

As it should be, because you are not using the correct type of response
codes..

Use this code instead:

    --- client ---

    IdTCPClient1.SendCmd('Hello', 200);


    --- server ---

    type
        TCmdSync = class(TIdSync)
        protected
            FCmd: String;
            procedure DoSynchronize; override;
        public
            constructor Create(const ACmd: String); reintroduce;
            class procedure Add(const ACmd: String);
        end;

    constructor TCmdSync.Create(const ACmd: String);
    begin
        inherited Create;
        FCmd := ACmd;
    end;

    procedure DoSynchronize;
    begin
        Form1.RichEdit1.Lines.Add(FCmd);
    end;

    class procedure TCmdSync.Add(const ACmd: String);
    begin
        with Create(ACmd) do try
            Synchronize;
        finally
            Free;
        end;
    end;

    procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);
    var
        lCmd: string;
    begin
        lCmd := Trim(AContext.Connection.IOHandler.ReadLn);
        TCmdSync.Add(lCmd);
        AContext.Connection.IOHandler.WriteLn('200 Welcome');
    end;


Now, with that said, you should consider using TIdCmdTCPServer instead of
TIdTCPServer.  The CommandHandlers mechanism is specifically designed for
the types of protocols that SendCmd() supports.  You can define a
CommandHandler item for each command that you want to support, complete with
full design-time support, automated parameter parsing, and automated
replying.  All you would have to do in your code is implement the OnCommand
event handlers to perform the operations that the commands are requesting,
and then assign the response data.  For example:

    --- server ---

    // add a HELLO CommandHandler to the TIdCmdTCPServer.CommandHandlers
    // proeprty at design-time, and then assign the following as its
OnCommand event handler

    procedure TForm1.IdCmdTCPServer1CommandHELLO(ASender: TIdCommand);
    begin
        TCmdSync.Add('HELLO Received');
        ASender.Reply.SetReply(200, 'Welcome');
    end;


Gambit

Replies:

In response to:

www.cryer.info
Managed Newsgroup Archive