需要使用TIdTelnet与telnet服务器交互的示例/演示

时间:2011-06-18 14:10:32

标签: delphi telnet indy

我尝试将Indy 10.5.5(Delphi 2010附带)用于:

  • 连接到telnet服务器
  • 执行用户名/密码验证(获取对命令shell的访问权限)
  • 执行命令并将结果数据返回给应用程序

并没有成功,另外我完全迷失在Indy内部的意大利面逻辑中,现在不知道为什么它不起作用或我应该如何将字符串发送到服务器并获取结果。需要一些示例代码来研究。


问题的正式形式:我在哪里可以获得第三方贡献的演示,涵盖TIdTelnet组件? (indyproject.org演示网页没有)

3 个答案:

答案 0 :(得分:5)

Telnet的主要问题是它不像大多数其他Internet协议那样使用命令/响应模型。任何一方都可以随时发送数据,并且每个方向的数据都与其他方向无关。这由TIdTelnet反映在它运行内部读取线程以接收数据的事实中。因此,您不能像在其他Indy组件中那样简单地连接,发送命令和等待单个代码块中的响应。您必须编写命令,然后等待OnDataAvailable事件触发,然后解析数据以确定它实际是什么(并准备好处理可能接收到部分数据的情况,因为这只是如何TCP / IP工作)。

如果要连接到实际实现命令/响应模型的服务器,那么最好直接使用TIdTCPClient而不是TIdTelnet(然后在服务器上手动执行任何Telnet序列解码)真的是使用Telnet,这在当今很少见,但并非不可能)。对于Indy 11,我们可能会重构TIdTelnet的逻辑以支持非线程版本,但尚未确定。

答案 1 :(得分:3)

用indy做完了。 没有评论..只是som旧代码:-) telnet不喜欢发送字符串kommand ..使用sendch。

telnetdude.Host := 1.1.1.1;
try
telnetdude.connect;
except
on E: Exception do begin
E.CleanupInstance;
end; {except}
if telnetdude.Connected then begin
for i := 1 to length(StringToSend) do telnetdude.sendch(StringToSend[i]);
telnetdude.sendch(#13);
end;
end; {while}
end; {if}
if telnetdude.Connected then telnetdude.Disconnect;
end;

答案 2 :(得分:1)

我希望这对寻求类似问题答案的人有所帮助。

首先,这似乎是典型的命令/响应模型(如上所述,实际上并不适用)。

因此,我只是将其用于某些非常简单的应用程序(重新启动路由器)。

Johnny Lanewood对上述代码的特定补充(也许有一些澄清) a)您必须发送#13来确认命令 b)我发送的每条命令都“挂起” /我请求直到启用ThreadedEvent的响应才挂起。 (这是我的大问题)

c)OnDataAvailable事件告诉您何时可以从Telnet服务器获得新数据-但是不能保证这些数据是什么-即,您在命令行中获得的内容很漂亮/以前添加的内容回应。但这不是命令的特定响应行-远程登录服务器返回的内容(可能是欢迎信息,ASCII绘图等)

鉴于上面的(c),宁愿检查OnDataAvailable事件并解析数据(知道您的期望)。当输出停止时(即您需要为此建立机制),您可以解析数据并确定服务器是否准备好从客户端进行新操作。出于下面我的代码的目的,我设置了一个读取超时,并且我只使用了Sleep(2000)-无知地期望没有错误,并且服务器将在睡眠后准备好下一条命令。 我最大的绊脚石是ThreadedEvent:= True(请参见上面的b)

因此,我的工作解决方案(对于特定的应用程序,可能对某些人来说是可怕的)。

   lIDTelnet := TIdTelnet.Create(nil);
    try
      lIdTelnet.ReadTimeout := 30000;
      lIDTelnet.OnDataAvailable := TDummy.Response;
      lIDTelnet.OnStatus := TDummy.Status;
      lIdTelnet.ThreadedEvent := True;

      try
        lIDTelnet.Connect('192.168.0.1', 23);
        if not lIDTelnet.Connected then
          Raise Exception.Create('192.168.0.1 TELNET Connection Failed');

        Sleep(2000);

        lIdtelnet.SendString(cst_user + #13);
        Sleep(2000);

        lIdtelnet.SendString(cst_pass + #13);
        Sleep(2000);

        lIdtelnet.SendString(cst_reboot + #13);
        Sleep(2000);

        if lIDTelnet.Connected then
           lIDTelnet.Disconnect;
      except
        //Do some handling
      end;
  finally 
    FreeAndNil(lIdTelnet);
  end;

然后

class procedure TDummy.Response(Sender: TIdTelnet; const Buffer: TIdBytes);
begin
  Write(TDummy.ByteToString(Buffer));
end;

class function TDummy.ByteToString(
  const aBytes: TIdBytes): String;
var
  i : integer;
begin
  result := '';
  for i := 0 to Length(aBytes) -1 do
  begin
    result := result + Char(aBytes[i]);
  end;
end;