4

使用 Indy10 - DelphiXE。如何告诉我正在连接的 telnet 服务器TIdTelnet不回显我发送给 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程序,但它受到保护,我该如何覆盖它的行为?

4

3 回答 3

5

如果服务器向IAC WILL ECHO您发送一个,TIdTelnet被硬编码以发送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当前状态没有改变,避免了无休止的响应循环)。

于 2013-06-20T16:29:04.640 回答
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 文件的副本;在项目管理器中将其链接到您的项目;然后按照上面概述的方式对该副本进行更正。

于 2013-08-14T07:48:31.190 回答
0

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

  1. 将 TIdConnectionIntercept 添加到您的表单中,并使用 Object Inspector 通过 Intercept 属性将其挂接到您的 TIdTelnet 组件中。

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

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

  4. 根据需要更改中间字节(即强制将 WILL 更改为 WONT 或 DO 更改为 DONT 以适应您要强制执行的内容)。

乔布斯是个“好人”

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

于 2013-08-14T08:04:22.083 回答