5

我有一小段代码通过 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;

所以我在家里用我的wifi网络开发了它,一切都很好。

当我重新开始工作时,我进行了测试,但我收到一条错误消息

Socket Errod # 10040 Message too long

在工作中,我们有固定的 IP,我和所有的计算机都在同一个子网中。

我试图断开与固定 IP 的连接并连接到 wifi,这当然是 DHCP,而不是在同一个子网中,它工作正常。

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

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

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

顺便说一句,我使用的是 delphi 2010,我认为它是 indy 10。我也在 XE2 上进行了测试,但同样的错误。

任何的想法

- - - 编辑 - - -

这个问题得到了回答,现在我尝试让这个在多线程中运行,并且我已经为 Delphi (XE2) Indy (10) Multithread Ping提出了另一个问题

4

3 回答 3

7

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;
于 2012-10-04T09:03:31.453 回答
1

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

要回答更神秘的修复:

ABuffer := MyIdIcmpClient1.Host + StringOfChar(' ', 255);

这是解决 Indy10 组件中存在错误的事实的“神奇”修复(如果我理解 Remy Lebeau 正确的话)。

我的猜测是这与接收缓冲区的大小有关。为了测试我的理论,我可以使用任何字符,根本不需要包含主机地址。仅使用接收缓冲区所需的尽可能多的字符。我使用这个小代码(C++ Builder XE5)非常成功地进行了 Ping(所有其他值都是默认值):

AnsiString Proxy = StringOfChar('X',IcmpClient->PacketSize);

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

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

也许这对@RemyLebeau 修复工作有帮助。

于 2014-02-10T03:10:37.907 回答
0

使用此代码

ABuffer := MyIdIcmpClient1.Host + StringOfChar(' ', 255);

MyIdIcmpClient.Ping(ABuffer);

于 2014-01-22T13:38:56.323 回答