Newsgroups : Borland : borland.public.delphi.internet.winsock : 2006 Mar : 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: | Sun, 26 Mar 2006 14:13:03 |
"Maxim Shiryaev" <MaximShiryaev@mail.ru> wrote in message
news:44250cf5$1@newsgroups.borland.com...
> The parameters will actually be UTF-8 strings decoded back
> to WideStrings at a server.
That is fine. A lot of protocols that support Unicode do that nowadays.
> So each parameter on individual line seems to be easier to parse.
As you have already seen, that is technically doable. But I do not
recommend that approach in general. It actually complicates the design of
your protocol, not makes it simplier.
> More over the number of parameters will be variable (I don't want
> to pass default values).
Having everything on a single line can handle that just as easily as using
separate lines.
> And they will be name-bound, not positional.
The examples I showed you earlier can be adapted to handle names inside the
parameters. In fact, the TIdCommand.Params property is a TStrings
descendant, so you can make use of its Values[] sub-property, ie:
GETDATA Param1=value1 Param3=value3
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
Param1, Param3: String
begin
Param1 = ASender.Params.Values['Param1'];
Param3 = ASender.Params.Values['Param3'];
//...
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 Param1=value1 Param3=value3',
200);
IdTCPClent1.IOHandler.Capture(LData);
// use LData as needed ...
finally
Sys.FreeAndNil(LData);
end;
end;
Alternatively:
--- server ---
uses
IdObjs, IdSys;
// make sure the TIdCommandHandler.ParseParams property is set to True
procedure TForm1.CommandGETDATA(ASender: TIdCommand);
var
I: Integer;
ParamName, ParamValue: String
begin
for I := 0 to ASender.Params.Count-1 do
begin
ParamValue := ASender.Params[I];
ParamName := Fetch(ParamValue, '=');
// use ParamName and ParamValue as needed ...
end;
ASender.Reply.SetReply(200, 'OK');
ASender.Response.Add('some string');
ASender.Response.Add('another string');
end;
> So I've decided to make the command ASCII only and pass parameters
> on additional lines.
I still do not recommend that approach. But it is your decision, not mine.
> It looks like we need an extended version of TIdTCPClient.
No, you do not.
> The current one lacks functions compared to its server counterpart.
As it should be, because TIdTCPClient is not a server component. However,
Indy 10 does have a TIdCmdTCPClient component, which has the exact same
CommandHandler support that TIdCmdTCPServer has.
> For example, an overloaded version of
>
> SendCmd(Command : string; Parameters: array of string;
> Header: TStrings=nil; Body: TStrings=nil)
>
> would be very useful.
No, it wouldn't. For starters, it would complicate TIdTCPClient itself.
And second, it has no use in any other Indy component at all, so there is no
reason to put it into Indy directly. What you ask for is custom behavior,
and as such you should be wrapping that kind of functionality in your own
function that formats the necessary values for the existing SendCmd() to
use.
> Can you give me some link to the docs about RFC-based protocols
Every protocol is described in its own separate RFC. The documentation
lists which component implements which RFCs.
> describing how to create a new application-level one.
There are no docs for that.
> All I found in Google are HTTP references. They describe structure of
> commands, headers, body, staus codes. etc.
That is what RFCs do to begin with.
> But I need a more general description.
Such as?
Gambit