Newsgroups : Borland : borland.public.delphi.internet.winsock : 2006 Mar : Re: Looking for client/server demo of a proprietary protocol based on TIdCmdTCPS

www.cryer.info
Managed Newsgroup Archive

Re: Looking for client/server demo of a proprietary protocol based on TIdCmdTCPS

Subject:Re: Looking for client/server demo of a proprietary protocol based on TIdCmdTCPS
Posted by:"Remy Lebeau (TeamB)" (no.spam@no.spam.com)
Date:Fri, 24 Mar 2006 12:51:38

"Maxim Shiryaev" <maxim@olma-press.ru> wrote in message
news:4423f949@newsgroups.borland.com...

> Let's I have a commad "GETDATA". It replies like:
>
> 200 OK
> Result1=some string
> Result2=another string
> .
<snip>
> Now I need to create a client. I want to pass some data (also
> encoded in TStrings) to my server and get the results back.

You need to use the WriteRFCStrings() and Capture() methods.  For example:

    --- server ---

    uses
        IdObjs, IdSys;

    procedure TForm1.CommandGETDATA(ASender: TIdCommand);
    var
        LParams: TIdStringList;
    begin
        LParams := TIdStringList.Create;
        try
            ASender.Context.Connection.IOHandler.Capture(LParams);
            // use LParams as needed...
            ASender.Reply.SetReply(200, 'OK');
            ASender.Response.Add('Result1=some string');
            ASender.Response.Add('Result2=another string');
        finally
            Sys.FreeAndNil(LParams);
        end;
    end;


    --- client ---

    uses
        IdObjs, IdSys;

    var
        LParams, LData: TIdStringList;
    begin
        LParams := TIdStringList.Create;
        try
            LData := TIdStringList.Create;
            try
                LParams.Add('Param1=value1');
                LParams.Add('Param2=value 2');
                IdTCPClient1.WriteLn('GETDATA');
                IdTCPClient1.IOHandler.WriteRFCStrings(LParams);
                IdTCPClient1.GetResponse(200);
                IdTCPClient1.IOHandler.Capture(LData);
                // use LData as needed ...
            finally
                Sys.FreeAndNil(LData);
            end;
        finally
            Sys.FreeAndNil(LParams);
        end;
    end;


With that said, it would be better if you put the params in the command
directly, not send them afterwards.  The SendCmd() and CommandHandler
architectures are well-designed for that approach.  For example:

    GETDATA value1 value2

    200 OK
    some string
    another string
    .

    --- server ---

    uses
        IdObjs, IdSys;

    // make sure the TIdCommandHandler.ParseParams property is set to True
    procedure TForm1.CommandGETDATA(ASender: TIdCommand);
    var
        I: Integer;
    begin
        for I := 0 to ASender.Params.Count do
        begin
            // use ASender.Params[I] as needed ...
        end;
        ASender.Reply.SetReply(200, 'OK');
        ASender.Response.Add('some string');
        ASender.Response.Add('another string');
    end;


    --- client ---

    uses
        IdObjs, IdSys;

    var
        LData: TIdStringList;
    begin
        LData := TIdStringList.Create;
        try
            IdTCPClient1.SendCmd('GETDATA value1 value2', 200);
            IdTCPClent1.IOHandler.Capture(LData);
            // use LData as needed ...
        finally
            Sys.FreeAndNil(LData);
        end;
    end;

If you need to send parameters that have spaces in them, then either:

1) define a unique value for the TIdCommandHandler.ParamDelimiter property
that will never appear in your parameter data:

    GETDATA value1|value 2

    200 OK
    some string
    another string
    .

    --- server ---

    uses
        IdObjs, IdSys;

    procedure TForm1.CommandGETDATA(ASender: TIdCommand);
    var
        I: Integer;
    begin
        for I := 0 to ASender.Params.Count do
        begin
            // use ASender.Params[I] as needed ...
        end;
        ASender.Reply.SetReply(200, 'OK');
        ASender.Response.Add('some string');
        ASender.Response.Add('another string');
    end;


    --- client ---

    uses
        IdObjs, IdSys;

    var
        LData: TIdStringList;
    begin
        LData := TIdStringList.Create;
        try
            IdTCPClient1.SendCmd('GETDATA value1|value 2', 200);
            IdTCPClent1.IOHandler.Capture(LData);
            // use LData as needed ...
        finally
            Sys.FreeAndNil(LData);
        end;
    end;

2) use set the TIdCommandHandler.ParseParams property to False and then
parse the TIdCommand.UnparsedParams property manually.

    GETDATA value1 "value 2"

    200 OK
    some string
    another string
    .

    --- server ---

    uses
        IdObjs, IdSys;

    procedure TForm1.CommandGETDATA(ASender: TIdCommand);
    var
        LTmp, LParam: String;
    begin
        LTmp := Sys.Trim(ASender.UnparsedParams);
        while LTmp <> '' do
        begin
            if LTmp[1] = '"' then begin
                Delete(LTmp, 1, 1);
                LParam := Fetch(LTmp, '"');
            end else begin
                LParam := Fetch(LTmp, ' ');
            end;
            // use LParam as needed ...
            LTmp := Sys.TrimLeft(LTmp);
        end;
        ASender.Reply.SetReply(200, 'OK');
        ASender.Response.Add('some string');
        ASender.Response.Add('another string');
    end;


    --- client ---

    uses
        IdObjs, IdSys;

    var
        LData: TIdStringList;
    begin
        LData := TIdStringList.Create;
        try
            IdTCPClient1.SendCmd('GETDATA value1 "value 2"', 200);
            IdTCPClent1.IOHandler.Capture(LData);
            // use LData as needed ...
        finally
            Sys.FreeAndNil(LData);
        end;
    end;


Gambit

Replies:

In response to:

www.cryer.info
Managed Newsgroup Archive