Delphi Indy Ping错误10040

Delphi Indy Ping错误10040,delphi,ping,indy10,Delphi,Ping,Indy10,我有一小段代码,通过ping来检查计算机是否处于活动状态。我们以前有一个房间,里面有40台电脑,我想通过我的程序远程检查,这个程序现在还活着 因此,我使用indy编写了一个小ping函数 function TMainForm.Ping(const AHost : string) : Boolean; var MyIdIcmpClient : TIdIcmpClient; begin Result := True; MyIdIcmpClient := TIdIcmpClient.Cr

我有一小段代码,通过ping来检查计算机是否处于活动状态。我们以前有一个房间,里面有40台电脑,我想通过我的程序远程检查,这个程序现在还活着

因此,我使用indy编写了一个小ping函数

function TMainForm.Ping(const AHost : string) : Boolean;
var
  MyIdIcmpClient : TIdIcmpClient;
begin
  Result := True;

  MyIdIcmpClient := TIdIcmpClient.Create(nil);
  MyIdIcmpClient.ReceiveTimeout := 200;
  MyIdIcmpClient.Host := AHost;

  try
    MyIdIcmpClient.Ping;
    Application.ProcessMessages;
  except
    Result := False;
    MyIdIcmpClient.Free;
    Exit;
  end;
  if MyIdIcmpClient.ReplyStatus.ReplyStatusType <> rsEcho Then result := False;

  MyIdIcmpClient.Free;
end;
在工作中,我们有固定的IP,所有的计算机和我都在同一个子网中

我试着从固定IP断开连接到wifi,wifi当然是DHCP,不在同一个子网中,它工作正常

我尝试在互联网上搜索这个错误以及如何解决它,但没有找到太多信息

当然,我已经尝试将默认缓冲区大小更改为一个更大的值,但它没有改变任何东西,我仍然在同一子网内的固定IP上收到错误

此外,我不知道这是否有助于找到解决方案,但我的代码处理异常,但在这种情况下,引发错误大约需要3-4秒,而超时设置为200毫秒。我不能在每一个ping上等那么久。

顺便说一句,我用的是Delphi2010,我认为它是indy 10。我也在XE2上进行了测试,但出现了相同的错误

有什么想法吗

----编辑---

这个问题得到了回答,现在我尝试在多线程中运行它,并为此问了另一个问题

PacketSize
属性设置为
24

function TMainForm.Ping(const AHost : string) : Boolean;
var
  MyIdIcmpClient : TIdIcmpClient;
begin
  Result := True;

  MyIdIcmpClient := TIdIcmpClient.Create(self);
  MyIdIcmpClient.ReceiveTimeout := 200;
  MyIdIcmpClient.Host := AHost;
  MyIdIcmpClient.PacketSize := 24;
  MyIdIcmpClient.Protocol := 1;
  MyIdIcmpClient.IPVersion := Id_IPv4;

  try
    MyIdIcmpClient.Ping;
    // Application.ProcessMessages; // There's no need to call this!
  except
    Result := False;
    Exit;
  end;
  if MyIdIcmpClient.ReplyStatus.ReplyStatusType <> rsEcho Then result := False;

  MyIdIcmpClient.Free;
end;
函数tmaninform.Ping(常量:字符串):布尔值;
变量
MyIdIcmpClient:TIdIcmpClient;
开始
结果:=真;
MyIdIcmpClient:=TIdIcmpClient.Create(self);
MyIdIcmpClient.ReceiveTimeout:=200;
MyIdIcmpClient.Host:=AHost;
MyIdIcmpClient.PacketSize:=24;
MyIdIcmpClient.Protocol:=1;
MyIdIcmpClient.IPVersion:=Id_IPv4;
尝试
MyIdIcmpClient.Ping;
//Application.ProcessMessages;//没必要叫这个!
除了
结果:=假;
出口
结束;
如果MyIdIcmpClient.ReplyStatus.ReplyStatusType rsEcho,则结果:=False;
MyIdIcmpClient.Free;
结束;
使用此代码

ABuffer:=MyIdIcmpClient1.Host+StringOfChar(“”,255)

MyIdIcmpClient.Ping(阿布弗)


对于XE5和Indy10,这仍然是一个问题,即使数据包大小不同

要回答更神秘的问题,请执行以下操作:

ABuffer := MyIdIcmpClient1.Host + StringOfChar(' ', 255);
这是一个“神奇”的修复,可以绕过Indy10组件中存在bug的事实(如果我正确理解Remy Lebeau的话)

我的推测是,这与接收缓冲区的大小有关。为了验证我的理论,我可以使用任何字符,根本不需要包含主机地址。只使用接收缓冲区所需的字符数。我使用这段小代码(C++Builder XE5)成功地执行了Ping(所有其他值均为默认值):

如您所见,我创建了一个与PacketSize属性长度相同的字符串。你用什么填充它是无关紧要的


也许这对@RemyLebeau进行修复时有帮助。

可能有防火墙阻止ICMP活动吗?是否调用了TidIcmpClient.OnReply?我已尝试将默认缓冲区大小更改为更大的值。具体如何更改?显示代码?也许你最好试着减少它。显示使用Windows API进行ping,缓冲区大小是消息大小,报告过大。还讨论了IdICMP:此代码存在内存泄漏:如果发生异常,组件将不会被释放。所有者应该是零,因为你想用同样的方法释放组件。@mjn你说得对,我编辑了我的代码。2件事。首先,它的工作原理是把24。你能解释一下原因吗?第二件事,我仍然要等3-4秒,有没有办法把这个时间减少到200-300毫秒?Orelse我应该使用多重触发,因为等待40 x 4=160秒太长了。顺便说一句,谢谢。我还不确定它为什么会起作用。。。但我相信这与大多数设备所接受的ICMP数据包的最大大小有关(我必须查一下)。您可以尝试使用更低的
PacketSize
来查看这是否会加快结果!您是否将
AHost
设置为主机名或IP地址?必须先将主机名解析为IP,然后才能向其发送任何数据。如果计算机的DNS子系统工作不正常或运行缓慢,解析可能需要额外的时间。无法在主机名解析上设置超时,因为这只是对操作系统的单个API调用。要设置超时,您必须使用
TIdDNSResolver
手动解析主机名。至于
PacketSize
,默认设置为1024。传递给
Ping()
(在本例中为空)的任何数据都将用于填充
PacketSize
在ICMP数据包中保留的空间。如果没有数据,则空间仍保留在数据包中。因此,减小
PacketSize
会减小ICMP数据包的总体大小。较小的ICMP数据包更适合网络数据包,因此更易于路由。仅供参考,
PacketSize
属性的默认值将在未来的Indy更新中降低,以解决此问题。您能否提供更多详细信息并解释您的代码回答此问题的原因?如果ABuffer是一个字符串,为什么在字符串末尾添加255倍的空格可以解决这个问题?
ABuffer := MyIdIcmpClient1.Host + StringOfChar(' ', 255);
AnsiString Proxy = StringOfChar('X',IcmpClient->PacketSize);

IcmpClient->Host = Host_Edit->Text;
IcmpClient->Ping(Proxy);