【问题标题】:TIdCommandHandler: How to construct commands?TIdCommandHandler:如何构造命令?
【发布时间】:2015-10-17 00:41:13
【问题描述】:

我正在使用 Delphi XE7。我以前从未使用过 Indy 组件。

我从 Embarcadero 找到了一个非常好的教程,名为 Developing TCP/IP-based Server Applications using Indy Components。它展示了一个使用TidCmdTCPServer 和命令处理程序的非常好的示例。

我的问题是我不明白如何构造命令。我在帮助文件和 Indy 主页都找不到它。

请看下面的代码:

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;

第一个命令HEARTBEAT 相当简单,但COLOR 命令则不然。

我没看懂这行:

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

谁能解释它是如何构造的?或者给我看一份文档,我可以在那里学习?

“不本地化”是什么意思?

【问题讨论】:

    标签: delphi indy indy10


    【解决方案1】:

    语法应该使用增强巴科斯-瑙尔形式 (BNF) 编写,类似于 RFC 822, Section 2 - NOTATIONAL CONVENTIONS 中定义的语法。

    COLOR 显然是命令名。

    &lt;sp&gt; 是一个空格字符。

    引号表示按原样显示的文字字符串。

    在这种情况下,| 被用作传输数据中参数之间的分隔符,因此应该放在引号中。

    [] 在这种情况下用于将逻辑项组合在一起。但是,括号出现在引号内,这是错误的,因为它们实际上并没有出现在传输中。

    color- 这种情况也没有实际传输,也不应该出现在语法中。

    所以,根据文章中提供的实际代码,服务器会接受以下命令(不区分大小写):

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

    在文章的客户端代码中可以清楚地看到:

    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;
    

    正确的语法因此应该定义如下:

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

    { do not localize } 向自动化国际化工具和翻译器提示,该行包含需要保持原样且未本地化为任何特定语言的字符串文字。

    话虽如此,文章还提到了这一点:

    由于我们选择使用 TidCmdTCPServer,我们不能简单地将一个放在表单上。相反,我们必须继承我们自己的基于 TidCmdTCPServer 的类,并将我们所有的自定义行为添加到它。即使 TidTCPServer 支持命令处理程序,这甚至是首选方式。

    这根本不是真的。 TIdCmdTCPServer.CommandHandlers 集合(Indy 9 中的 TIdTCPServer.CommandHandlers)在设计时可用,并且可以使用 Object Inspector 及其内置的集合编辑器完全编辑,包括分配每个命令的事件处理程序。这是使用它的首选方式,而且一直如此。派生自定义组件的唯一原因是如果您需要模块化命令处理代码以使其可重用(Indy 有一些自己的TIdCmdTCPServer 派生组件)。否则,派生和安装新组件就太过分了。

    【讨论】:

      猜你喜欢
      • 2021-01-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多