如何使用TO Telnet抑制回声?

时间:2013-06-20 13:44:28

标签: delphi telnet indy10

使用Indy10 - DelphiXE。 如何告诉我与TIdTelnet连接的telnet服务器不回显我发送给telnet服务器的命令?

这是我当前的尝试(不起作用),我尝试在每次telnet写入时发送序列IAC DO SUPPRESS_LOCAL_ECHO,但我相信这必须在协商阶段完成吗?

uses
  TIdTelnet,

...
procedure TIOTelnetConnection.SendSupressEcho;

var
  Resp: TIdBytes;

begin
 SetLength(Resp, 3);
 Resp[0] := TNC_IAC;
 Resp[1] := TNC_DO;
 Resp[2] := TNO_SUPLOCALECHO;
 FIOConnection.IOHandler.Write(Resp);
end;

procedure TIOTelnetConnection.Write(Str: AnsiString);
begin
 SendSupressEcho;
 if Str <> '' then
  FIOConnection.IOHandler.Write(Str);
end;

查看TIdTelnet来源我看到Negotiate程序,但它受到保护,我该如何覆盖它的行为?

3 个答案:

答案 0 :(得分:5)

如果服务器向您发送IAC WILL ECHOTIdTelnet会被硬编码以发送IAC DO ECHO响应,然后触发OnTelnetCommand(tncNoLocalEcho)事件,告诉您不要本地回应你发送的内容。

如果服务器向您发送IAC WONT ECHO,则TIdTelnet会被硬编码以发送IAC DONT ECHO响应,然后触发OnTelnetCommand(tncLocalEcho)事件以告知您本地回应你发送的内容。

如果服务器向您发送IAC DO ECHO,则TIdTelnet会被硬编码以发送IAC WILL ECHO响应,然后触发OnTelnetCommand(tncEcho)事件以告知您回显回到你收到的任何东西。

如果服务器向您发送IAC DONT ECHO,则TIdTelnet会被硬编码以发送IAC WONT ECHO响应,然后触发OnTelnetCommand(tncLocalEcho)事件以告知您回显回到你收到的任何东西。

因此,如果您不希望服务器回显给您,您可以向服务器发送IAC DONT ECHO命令,而不是IAC DO SUPLOCALECHO命令。然后,服务器将相应地回复IAC WONT ECHOIAC WILL ECHO(显然TIdTelnet将会回复,但服务器将不再响应,因为其ECHO当前状态不要改变,避免无休止的响应循环。)

答案 1 :(得分:0)

@Remy Lebeau:据我了解,你说的是: 如果服务器向您发送IAC DO ECHO,TIdTelnet将被硬编码为发送IAC WILL ECHO响应,然后触发OnTelnetCommand( tncEcho )事件告诉您回应你收到的任何东西。

这是有道理的,并且同意RFC857要实现的目标......

但是,在我们的代码中:

procedure TIdTelnet.Negotiate;
...
      TNC_DONT:
        begin
          b := IOHandler.ReadByte;
          case b of
            TNO_ECHO:
              begin
                DoTelnetCommand(tncEcho);
                //DoStatus('ECHO');    {Do not Localize}
                Reply := TNC_WONT;
              end;
            else
              Reply := TNC_WONT;
          end;

  TNC_DO:
    begin
      b := IOHandler.ReadByte;
      case b of
        TNO_ECHO:
          begin
            Reply := TNC_WILL;
            DoTelnetCommand(tncLocalEcho);
          end;

肯定这段代码不正确? (在Indy的10.6.0.497版本中)

我相信这会更有意义:

 procedure TIdTelnet.Negotiate;
 ...
      TNC_DONT:
         begin
           b := IOHandler.ReadByte;
           case b of
             TNO_ECHO:
               begin
               // Agree not to echo back everything received from server 
               // (This being the default - you shouldn't echo unless asked to)
                  Reply := TNC_WONT;            
               // Therefore only print locally what is sent to server
               // (Again: this is the default behavior without negotiation) 
                  DoTelnetCommand(tncLocalEcho);
               end;
             else
               Reply := TNC_WONT;
           end;

   TNC_DO:
     begin
       b := IOHandler.ReadByte;
       case b of
         TNO_ECHO:
           begin
           // Agree to echo back everything received from server 
              Reply := TNC_WILL;
              DoTelnetCommand(tncEcho); 
           // Therefore you may still have to locally print what you send
           // (i.e. local echo is usually still implicit in this)
           end;   

换句话说,我相信代码目前与它应该是交换的 - 这是发送DO ECHO的服务器应该忘记tncEcho令牌 - 这就是你在上面的引用中所说的!

这个错误如何在这么长时间内幸免于难? (可能是因为大多数Telnet服务器不再烦扰RFC857回声协商)

不幸的是,我目前看到“补偿”此错误的唯一方法是创建IDTelnet.pas文件的副本;在项目经理中链接到您的项目;然后如上所述对该副本进行更正。

答案 2 :(得分:0)

要解决最初的问题:“如何用TIdTelnet来抑制回声?”,我建议采取以下步骤:

  1. 将TIdConnectionIntercept添加到表单并将其挂钩到您的表单中 TIdTelnet组件通过使用Object的Intercept属性 检查员。

  2. 为TIdConnectionIntercept OnSend生成事件处理程序 事件

  3. 用它来检测其变量ABuffer:TIdBytes参数何时获得 响应服务器关于回显的协商命令。 请注意,缓冲区将完全且仅包含所有三个字节 由于响应被填充和发送的方式响应 TIdTelnet.Negotiate

  4. 根据需要更改中间字节(即强制执行从WILL到WONT的更改或DO到DONT以适应您要执行的操作)。

  5. 约伯是一个“好人”

    当然要记住,这种技术会在调用TidTelnet OnTelnetCommand之后注入更改,因此您必须更改在该处理程序中设置的任何内容以适应修改后的响应。