简体   繁体   中英

TIdCommandHandler: How to construct commands?

I'm using Delphi XE7. I've never used Indy components before.

I found a very good tutorial from Embarcadero called Developing TCP/IP-based Server Applications using Indy Components . It shows a very good example using TidCmdTCPServer and Command Handlers.

My problem is I did not understand how to construct a command. I couldn't find it in help files neither Indy homepage.

See the code below:

procedure TMyServer.InitializeCommandHandlers;
var
    NewCmd: TIdCommandHandler;
begin
    NewCmd                            := FCommandHandlers.Add;
    NewCmd.Command                    := 'HEARTBEAT'; { Do not Localize }
    NewCmd.OnCommand                  := CommandHEARTBEAT;
    NewCmd.ExceptionReply.NumericCode := 550;
    NewCmd.Description.Text           := 'Syntax: HEARTBEAT'; { do not localize }
    NewCmd.Disconnect                 := False;

    NewCmd                            := FCommandHandlers.Add;
    NewCmd.Command                    := 'COLOR'; { Do not Localize }
    NewCmd.CmdDelimiter               := #$20;
    NewCmd.ParamDelimiter             := '|';
    NewCmd.OnCommand                  := CommandCOLOR;
    NewCmd.ExceptionReply.NumericCode := 550;
    NewCmd.Description.Text           := 'Syntax: COLOR <sp> "GET | [SET" | color-"blue | red | yellow]"'; { do not localize }
    NewCmd.Disconnect                 := False;
end;

The first command HEARTBEAT is fairly easy, but the COLOR command is not.

I didn't understand the line:

NewCmd.Description.Text           := 'Syntax: COLOR <sp> "GET | [SET" | color-"blue | red | yellow]"'; { do not localize }

Can anyone explain how it is constructed? Or show me a document where I can learn this?

What "do not localize" means?

The syntax should have been written using Augmented Backus-Naur Form (BNF), similar to that defined in RFC 822, Section 2 - NOTATIONAL CONVENTIONS .

COLOR is the command name, obviously.

<sp> is a space character.

Quotes mean literal strings that appear as-is.

In this case, | is being used as a delimiter between parameters in the transmitted data, and as such should have been in quotes.

[] in this case is being used to group logical items together. However, the brackets appear inside of quotes, which is wrong because they do not actually appear in the transmission.

color- is this case is not actually transmitted, either, and should not have been in the syntax either.

So, based on the actual code provided in the article, the server will accept the following commands (case insensitive):

HEARTBEAT
COLOR GET
COLOR SET|BLUE
COLOR SET|RED
COLOR SET|YELLOW 

Which you can clearly see in the article's client code:

IdTCPClient1.Socket.WriteLn('HEARTBEAT');

IdTCPClient1.IOHandler.WriteLn('COLOR GET');

case RadioGroup1.ItemIndex of
  0: IdTCPClient1.IOHandler.WriteLn('COLOR SET|BLUE');
  1: IdTCPClient1.IOHandler.WriteLn('COLOR SET|RED');
  2: IdTCPClient1.IOHandler.WriteLn('COLOR SET|YELLOW');
end;

The correct syntax should thus be defined as follows:

NewCmd.Description.Text := 'Syntax: COLOR <sp> ("GET" / ("SET" "|" ("BLUE" / "RED" / "YELLOW")))'; { do not localize }

The { do not localize } is a hint to automated internationalization tools and translators that the line contains string literals that need to be left as-is and not localized to any particular language.

That being said, the article also mentions this:

Since we have chosen to use TidCmdTCPServer we cannot simply put one on a form. We must instead descend our own class base on TidCmdTCPServer and add all of our custom behavior to it. This was even the prefered way to go even when TidTCPServer supported command handlers.

This is simply not true at all. The TIdCmdTCPServer.CommandHandlers collection ( TIdTCPServer.CommandHandlers in Indy 9) is available at design-time and is fully editable using the Object Inspector and its built-in collections editor, including assigning per-command event handlers. THAT is the preferred way to use it, and always has been. The only reason to derive a custom component is if you need to modularize the command handling code to make it reusable (Indy has a few TIdCmdTCPServer derived components of its own). Otherwise, deriving and installing a new component is overkill.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM