Delphi 如何使用TIdTelnet抑制回声?
使用Indy10-DelphiXE。 我如何告诉我使用Delphi 如何使用TIdTelnet抑制回声?,delphi,telnet,indy10,Delphi,Telnet,Indy10,使用Indy10-DelphiXE。 我如何告诉我使用TIdTelnet连接的telnet服务器不要回显我向telnet服务器发送的命令 这是我目前的尝试(不起作用),我尝试在每次telnet写入时发送序列IAC DO SUPPRESS_LOCAL_ECHO,但我相信这必须在协商阶段完成 uses TIdTelnet, ... procedure TIOTelnetConnection.SendSupressEcho; var Resp: TIdBytes; begin SetL
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,
...
程序TIOTelnetConnection.SENDUPRSSECHO;
变量
Resp:TIdBytes;
开始
设定长度(分别为3);
Resp[0]:=TNC_IAC;
Resp[1]:=TNC_DO;
Resp[2]:=TNO_SUPLOCALECHO;
FIOConnection.IOHandler.Write(Resp);
结束;
过程TIOTelnetConnection.Write(Str:AnsiString);
开始
Sendsessecho;
如果Str“”那么
FIOConnection.IOHandler.Write(Str);
结束;
查看
TIdTelnet
源代码,我看到了协商
过程,但它是受保护的,我如何覆盖它的行为?如果服务器向您发送IAC WILL ECHO
,TIdTelnet
硬编码以发送IAC DO ECHO
响应,然后触发OnTelnetCommand(tncnolicalecho)
事件,告诉您不要在本地回显您发送的内容
如果服务器向您发送
IAC WONT ECHO
,TIdTelnet
将被硬编码为发送IAC DONT ECHO
响应,然后触发OnTelnetCommand(tncLocalEcho)
事件,告诉您本地回显您发送的内容
如果服务器向您发送
IAC DO ECHO
,TIdTelnet
被硬编码为发送IAC将ECHO
响应,然后触发OnTelnetCommand(tncEcho)
事件,告诉您回显收到的任何内容
如果服务器向您发送
IAC DONT ECHO
,TIdTelnet
被硬编码为发送IAC WONT ECHO
响应,然后触发OnTelnetCommand(tncLocalEcho)
事件,告诉您回显收到的任何内容
因此,如果您不希望服务器回显给您,您可以向服务器发送一个
IAC DONT echo
命令,而不是IAC DO SUPLOCALECHO
命令。然后服务器将相应地使用IAC WONT echo
或IAC will echo
进行回复(显然,TIdTelnet
会回复,但服务器不会再次回复,因为它的ECHO
当前状态不会改变,从而避免了无休止的响应循环)。@Remy Lebeau:据我所知,你是说:
如果服务器向您发送IAC DO回显,则TIdTelnet将硬编码为发送IAC WILL回显响应,然后触发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;
及
该代码肯定不正确?(在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;
及
换言之,我相信代码现在已经从它应该是的东西中被交换了,也就是说发送DO ECHO的服务器应该生成tncEcho令牌,这就是您在上面的引用中所说的
这个bug是如何存活这么长时间的?(可能是因为大多数Telnet服务器不再为RFC857回声协商而烦恼了)
不幸的是,目前我看到的唯一“补偿”此错误的方法是创建IDTelnet.pas文件的副本;在项目经理中将其链接到您的项目;然后对该副本进行如上所述的更正。来解决最初的问题:“如何使用TIdTelnet抑制echo?”,我建议采取以下步骤:
当然,请记住,此技术会在调用TidTelnet OnTelnetCommand后注入更改,因此您必须更改在该处理程序中设置的任何内容,以适应修改后的响应。谢谢,我发现这有点让人困惑,但事实上IAC DONT ECHO正是我要寻找的序列。有没有可能在稍后将其更改为属性Indy?
TIdTelnet
的修订非常简单,因此我确信在未来的版本中可以做很多事情来改进它。不幸的是,我发现在客户端强制执行DONT将导致用Delphi XE4编写的服务器在IOHandler中引发断言异常!这似乎是因为硬编码n TidTelnet生成一个额外的响应:即我们得到序列WILL->DONT->WONT->DONT(最后一个DONT不应该发生)。意外的3字节命令可能会导致服务器(在启用Unicode支持的情况下编写)检测到“缺少的字节”并引发断言异常。总结一下:(a)TidTelnet将在will-DONT-WONT序列中频繁应答一次,并且(b)TidTelnetServer可能存在与接收意外奇数字节序列相关的错误。这可能是因为我必须使用result:=AContext.Connection.IoHandler.WaitFor(chr(TNC_IAC),False,False,Indy8BitEncoding,Timeout);在服务器代码中,因为“WaitFor”没有TidByte重载。这种重载的省略可能是问题的核心-尽管我仍然认为意外传入的数据使服务器崩溃并导致其光盘损坏不是很好
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;