I have a small piece of code that checks if a computer is alive by pinging it. We use to have a room with 40 computer and I wanna check remotely through my program which on is alive.

Therefore I wrote a little ping function using indy

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;

So I’ve developped that at home on my wifi network and everthing just work fine.

When I get back to work I tested and I get an error saying

Socket Errod # 10040 Message too long

At work we have fixed IPs and all the computer and I are in the same subnet.

I tried to disconnect from the fixed IP and connect to the wifi which of course is DHCP and not in the same subnet, and it is just working fine.

I have tried searching the internet for this error and how to solve it but didn’t find much info.

Of course I have tried to change the default buffer size to a larger value but it didn’t change anything I still get the error on the fixed IP within same subnet.

Moreover, I don’t know if this can help finding a solution, but my code treats exceptions, but in that case it takes about 3-4 seconds to raise the error whereas the Timeout is set to 200 milliseconds. And I cannot wait that long over each ping.

By the way I use delphi 2010 and I think it is indy 10. I also have tested on XE2 but same error.

Any idea

—– EDIT —–

This question is answered, now I try to have this running in multithread and I have asked another question for that
Delphi (XE2) Indy (10) Multithread Ping

У меня есть небольшой фрагмент кода, который проверяет, жив ли компьютер, пингуя его. У нас есть комната с 40 компьютерами, и я хочу удаленно проверить свою программу, которая работает.

Поэтому я написал небольшую функцию ping, используя indy

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;

Итак, я разработал это дома в своей сети Wi-Fi, и все работает нормально.

Когда я вернусь к работе, я проверил, и я получаю сообщение об ошибке

Socket Errod # 10040 Message too long

На работе у нас фиксированные IP и все компьютер и я находимся в одной подсети.

Я попытался отключиться от фиксированного IP-адреса и подключиться к Wi-Fi, который, конечно же, является DHCP, а не в той же подсети, и он просто работает нормально.

Я попытался найти в Интернете эту ошибку и способы ее решения, но не нашел много информации.

Конечно, я попытался изменить размер буфера по умолчанию на большее значение, но это ничего не изменило. Я все еще получаю сообщение об ошибке на фиксированном IP-адресе в той же подсети.

Более того, я не знаю, поможет ли это найти решение, но мой код обрабатывает исключения, но в этом случае для возникновения ошибки требуется около 3-4 секунд, тогда как время ожидания установлено на 200 миллисекунд. И я не могу так долго ждать каждого пинга.

Кстати, я использую delphi 2010, и я думаю, что это инди 10. Я также тестировал XE2, но та же ошибка.

Любая идея

—– ИЗМЕНИТЬ —–

На этот вопрос дан ответ, теперь я пытаюсь запустить его в многопоточном режиме и задал для этого другой вопрос Delphi (XE2) Indy (10) Многопоточный Ping

У меня есть небольшой фрагмент кода, который проверяет, жив ли компьютер, проверяя его. У нас есть комната с 40 компьютерами, и я хочу удаленно проверить мою программу, которая включена.

Поэтому я написал небольшую функцию ping, используя indy

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;

Так что я разработал это дома в моей сети Wi-Fi, и все просто отлично работает.

Когда я вернусь к работе, я проверил, и я получаю сообщение об ошибке

Socket Errod # 10040 Message too long

На работе у нас есть фиксированные IP-адреса и все мы с компьютером в одной подсети.

Я попытался отключиться от фиксированного IP-адреса и подключиться к Wi-Fi, который, конечно, DHCP, а не в той же подсети, и он просто работает нормально.

Я пытался найти в интернете эту ошибку и как ее решить, но не нашел много информации.

Конечно, я попытался изменить размер буфера по умолчанию на большее значение, но это ничего не изменило, но я все равно получаю сообщение об ошибке на фиксированном IP в той же подсети.

Более того, я не знаю, может ли это помочь найти решение, но мой код обрабатывает исключения, но в этом случае требуется около 3-4 секунд, чтобы вызвать ошибку, тогда как время ожидания установлено на 200 миллисекунд. И я не могу так долго ждать каждого пинга.

Кстати, я использую Delphi 2010, и я думаю, что это инди 10. Я также тестировал на XE2, но та же ошибка.

Любая идея

—– РЕДАКТИРОВАТЬ —–

На этот вопрос дан ответ, теперь я пытаюсь запустить его в многопоточном режиме и задаю другой вопрос для этого многопоточного Ping Delphi (XE2) Indy (10)

Solution 1

Set the PacketSize property to 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;

Solution 2

For XE5 and Indy10 this is still a problem, even with different Packet Size.

To answer the more cryptical fix:

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

This is a “magic” fix to get around the fact that there is a bug in the Indy10 component (if I have understood Remy Lebeau right).

My speculation is that this has some connection with the size of the receive buffer. To test my theory I can use any character and don’t need to include the host address at all. Only use as many character you need for the receive buffer. I use this small code (C++ Builder XE5) to do a Ping with great success (all other values at their defaults):

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

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

As you can see I create a string of the same length as the PacketSize property. What you fill it with is insignificant.

Maybe this can be of help to @RemyLebeau when he work on the fix.

Comments

  • I have a small piece of code that checks if a computer is alive by pinging it. We use to have a room with 40 computer and I wanna check remotely through my program which on is alive.

    Therefore I wrote a little ping function using indy

    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;
    

    So I’ve developped that at home on my wifi network and everthing just work fine.

    When I get back to work I tested and I get an error saying

    Socket Errod # 10040 Message too long
    

    At work we have fixed IPs and all the computer and I are in the same subnet.

    I tried to disconnect from the fixed IP and connect to the wifi which of course is DHCP and not in the same subnet, and it is just working fine.

    I have tried searching the internet for this error and how to solve it but didn’t find much info.

    Of course I have tried to change the default buffer size to a larger value but it didn’t change anything I still get the error on the fixed IP within same subnet.

    Moreover, I don’t know if this can help finding a solution, but my code treats exceptions, but in that case it takes about 3-4 seconds to raise the error whereas the Timeout is set to 200 milliseconds. And I cannot wait that long over each ping.

    By the way I use delphi 2010 and I think it is indy 10. I also have tested on XE2 but same error.

    Any idea

    —– EDIT —–

    This question is answered, now I try to have this running in multithread and I have asked another question for that
    Delphi (XE2) Indy (10) Multithread Ping

Recents

Related

I have a small piece of code that checks if a computer is alive by pinging it. We use to have a room with 40 computer and I wanna check remotely through my program which on is alive.

Therefore I wrote a little ping function using indy

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;

So I’ve developped that at home on my wifi network and everthing just work fine.

When I get back to work I tested and I get an error saying

Socket Errod # 10040 Message too long

At work we have fixed IPs and all the computer and I are in the same subnet.

I tried to disconnect from the fixed IP and connect to the wifi which of course is DHCP and not in the same subnet, and it is just working fine.

I have tried searching the internet for this error and how to solve it but didn’t find much info.

Of course I have tried to change the default buffer size to a larger value but it didn’t change anything I still get the error on the fixed IP within same subnet.

Moreover, I don’t know if this can help finding a solution, but my code treats exceptions, but in that case it takes about 3-4 seconds to raise the error whereas the Timeout is set to 200 milliseconds. And I cannot wait that long over each ping.

By the way I use delphi 2010 and I think it is indy 10. I also have tested on XE2 but same error.

Any idea

—– EDIT —–

This question is answered, now I try to have this running in multithread and I have asked another question for that
Delphi (XE2) Indy (10) Multithread Ping

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *