Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   IsHostAlive mit XE2 - Unklare Fehler / Warnungen (https://www.delphipraxis.net/179515-ishostalive-mit-xe2-unklare-fehler-warnungen.html)

Piro 12. Mär 2014 09:34

IsHostAlive mit XE2 - Unklare Fehler / Warnungen
 
Moin zusammen,

ich verwende aus der CodeLibrary die IsHostAlive Unit, welche ich sehr gerne benutze. Ich musste aber die Umwandlung der Strings in PAnsiString anpassen und verwende dafür eine Funktion. Habe ich im Netz gefunden. Vielleicht geht es ja einfacher.
Delphi-Quellcode:
unit uHostAlive;

...

function StringToPAnsiChar(stringVar : string) : PAnsiChar;
Var
  AnsString : AnsiString;
  InternalError : Boolean;
begin
  InternalError := false;
  Result := '';
  try
    if stringVar <> '' Then
    begin
       AnsString := AnsiString(StringVar);
       Result := PAnsiChar(PAnsiString(AnsString));
    end;
  Except
    InternalError := true;
  end;
end;

function IsHostAlive(Hostname: String; pTripTime: PCardinal = nil; Timeout: Integer = 5000; TTL: Integer = 255): Boolean;
const
  SendBuffer: array[0..31] of char =
              ('p', 'i', 'n', 'g', 'p', 'o', 'n', 'g',
               'p', 'i', 'n', 'g', 'p', 'o', 'n', 'g',
               'p', 'i', 'n', 'g', 'p', 'o', 'n', 'g',
               'p', 'i', 'n', 'g', 'p', 'o', 'n', 'g');
var
  WSA: TWSADATA;
  Reply: PICMP_ECHO_REPLY;
  Addr: Integer;
  hIcmp: cardinal;
  Options: IP_OPTION_INFORMATION;

  function ResolveHost(Hostname: String): Integer;
  type
    PPInAddr= ^PInAddr;
  var
    HostInfo: PHostEnt;
    T: PPInAddr;
  begin
    t:= nil;
    Result:= inet_addr(PAnsiChar(Hostname)); // mit XE2 ging PChar nicht mehr aber PAnsiChar
    if result = INADDR_NONE then begin                      
       HostInfo:= gethostbyname(StringToPAnsiChar(Hostname)); // mit XE2 ging PChar und PAnsiChar nicht mehr, deshalb die Funktion
       if HostInfo <> nil then
          T:= Pointer(HostInfo^.h_addr_list);
       if (T <> nil) and (T^<> nil) then begin
          Result:= T^^.S_addr;
       end;
    end;
  end;

begin
  Result:= False;
  FillChar(Options, sizeof(IP_OPTION_INFORMATION), #0);
  Reply:= nil;
  options.TTL:= TTL;
  options.TOS:= 1;
  if WSAStartUp(((0 shl 8)+2), WSA) = 0 then begin
     Addr:= ResolveHost(Hostname);
     if Addr <> INADDR_NONE then begin
        hIcmp:= IcmpCreateFile();
        if hicmp <> INVALID_HANDLE_VALUE then try
           Reply:= AllocMem(sizeof(ICMP_ECHO_REPLY)+sizeof(SendBuffer));
           IcmpSendEcho(hIcmp, Addr, @SendBuffer[0], sizeof(SendBuffer), @Options, Reply, sizeof(ICMP_ECHO_REPLY)+sizeof(SendBuffer), timeout);
           Result:= (Reply^.Status = 0);
           if Result and (pTripTime <> nil) then
              pTripTime^:= Reply^.RoundTripTime;
        finally
           IcmpCloseHandle(hIcmp);
           if Reply <> nil then
              FreeMem(Reply);
           WSACleanup();
        end;
     end else begin
        WSACleanup();
       // Hostname konnte nicht aufgelöst werden.
     end;
  end else begin
       // Winsock konnte nicht gestartet werden.
  end;
end;

end.
Leider macht mir die Unit seit der Umstellung auf XE2 Pro Ärger und meine Computer und Server sind nie erreichbar.

Die Vergleiche sind immer gleich (True oder False) laut Compilier.
Delphi-Quellcode:
if result = INADDR_NONE then begin // [DCC Warnung] uHostAlive.pas(79): W1021 Der Vergleich ergibt immer False
                                   // [DCC Warnung] uHostAlive.pas(79): W1023 Vorzeichenbehaftete und -lose Typen werden verglichen - beide Operanden werden erweitert

...

Addr:= ResolveHost(Hostname);
if Addr <> INADDR_NONE then begin // [DCC Warnung] uHostAlive.pas(97): W1022 Der Vergleich ergibt immer True
                                  // [DCC Warnung] uHostAlive.pas(97): W1023 Vorzeichenbehaftete und -lose Typen werden verglichen - beide Operanden werden erweitert
Wie gesagt, die Probleme hatte ich mit meiner früheren Version TurboDelphi Pro nicht. Ich könnte die Warnungen ja ignorieren aber die Computer / Server sind laut Rückgabewert nie erreichbar und das stimmt nicht.
Ich hoffe, einer von euch geht die Probleme und einen Lösungsansatz. Würde ungern auf diese Unit verzichten.

Gruß Sven

himitsu 12. Mär 2014 10:00

AW: IsHostAlive mit XE2 - Unklare Fehler / Warnungen
 
Wie ist INADDR_NONE deklariert?


Zitat:

Delphi-Quellcode:
function StringToPAnsiChar(stringVar : string) : PAnsiChar;
Var
  AnsString : AnsiString;
  InternalError : Boolean;
begin
  InternalError := false;
  Result := '';
  try
    if stringVar <> '' Then
    begin
       AnsString := AnsiString(StringVar);
       Result := PAnsiChar(PAnsiString(AnsString));
    end;
  Except
    InternalError := true;
  end;
end;

Was soll das InternalError darstellen?
Die Variable wird ja nie verwendet/ausgelesen.

Solange niemand bei stringVar das Speichernmanagement zerschießt, wird es dort auch niemals eine Exception geben.
OK, bei einem EOutOfMemory, aber so oder so ... dann ist eh alles zu spät.

Ein Zeiger auf den Speicher der lokalen Variable?
Diese Variable wird bei Prozedurende freigegeben und demnach enthält dann auch das Result einen ungültigen Zeiger.

Den AnsiString einfach so in einen PAnsiString zu casten ist garantiert auch total falsch.
Aber ermutlich wolltest du das
Delphi-Quellcode:
Result := PAnsiChar(Pointer(AnsString));
erreichen, also daß Delphi keine automatischen Konvertierungen bei AnsiString/PAnsiChar einbaut.


Entweder du machst Hostname direkt zu einem AnsiString (dessen Typ ändern),
oder halt nur temporär, aber dann so, daß die TempVariable lange genug überlebt.
Delphi-Quellcode:
gethostbyname(PAnsiChar(AnsiString(Hostname)));

// wird intern zu
AutomatischGenierierteAnsiStringVariable := AnsiString(Hostname);
gethostbyname(PAnsiChar(AutomatischGenierierteAnsiStringVariable));


Zitat:

Zitat von Piro (Beitrag 1251654)
Leider macht mir die Unit seit der Umstellung auf XE2 Pro Ärger und meine Computer und Server sind nie erreichbar.

Das Ganze war vorher noch ANSI? (vor D2009)

Zitat:

Delphi-Quellcode:
const
  SendBuffer: array[0..31] of char = 'pingpongpingpongpingpongpingpong'; // ja, das geht auch so

Also das CHAR war vorher ein AnsiChar?
Tja, dann stimmt dein Protokoll jetzt nicht mehr, denn jetzt ist es Unicode. :stupid:

Piro 12. Mär 2014 19:16

AW: IsHostAlive mit XE2 - Unklare Fehler / Warnungen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Danke für die schnelle Hilfe.

Die Variable
Zitat:

INADDR_NONE
habe ich nicht gesetzt. Habe den Code 1:1 aus der CodeLibrary.

Hat aber bis dato auch funktioniert. Im Anhang findest du den aktuellen Wert zur Laufzeit. Scheint ein willkürlicher Wert zu sein.
Was muss denn die Variable für einen Wert haben. Dachte immer das die Variable eine Konstante ist.

Übrigens habe ich die Umwandlungsfunktion nur 1:1 kopiert und nicht den Code angepasst. :-)

himitsu 12. Mär 2014 19:58

AW: IsHostAlive mit XE2 - Unklare Fehler / Warnungen
 
Tja, das kommt davon, wenn falsche Typen verwendet werden.

Das hat gefälligst ein Cardinal, DWORD oder Dergleichen zu sein, wie man am MSDN-Library durchsucheninet_addr sehen kann.

Es wurde aber als Integer definiert und ein Integer kann nunmal "logisch" niemals den Wert $FFFFFFFF (4294967295 :zwinker:) enthalten.
OK, binär wäre es die -1, aber eine Compiler, welcher genau auf die Typen achtet, wird bei diesem Vergleich beide Typen auf Int64 erweitern.
Und da er die Grenzen des Integers kennt, gibt er natürlich die Warnung aus, daß ein Vergleich niemals zutreffen wird, da es den Wert halt nicht geben kann.
Lösung:
Delphi-Quellcode:
if DWORD(Addr) <> INADDR_NONE then
, oder man berichtigt eben die Typen.


Ich hab auch gleich noch ein paar andere Typen angepasst (THandle statt Cardinal usw.)
Und melde gleich meine Antwort, so daß der CodeLib-Eintrag berichtigt wird.

Quelle: http://www.delphipraxis.net/126574-i...rreichbar.html

PS: Genau aus solchen Gründen, also wegen falschen Typen gibt es die meisten Probleme, vorallem bei solchen Umstellungen wie von ANSI zu Unicode oder von Win32 auf Win64.

Delphi-Quellcode:
unit hostalive;

interface

uses
  Windows, Winsock; // Winapi.Windows, Winapi.Winsock;

function IsHostAlive(Hostname: String; pTripTime: PCardinal=nil; Timeout: Integer=1000; TTL: Integer=255): Boolean;

implementation

type
  IP_OPTION_INFORMATION = packed record
    TTL:        Byte;
    TOS:        Byte;
    Flags:      Byte;
    OptionsSize: Byte;
    OptionsData: PAnsiChar;
  end;
  PIP_OPTION_INFORMATION = ^IP_OPTION_INFORMATION;

  ICMP_ECHO_REPLY = packed record
    Address:      in_addr;
    Status:       Cardinal;
    RoundTripTime: Cardinal;
    DataSize:     Word;
    Reserved:     Word;
    Data:         Pointer;
    Options:      IP_OPTION_INFORMATION;
  end;
  PICMP_ECHO_REPLY = ^ICMP_ECHO_REPLY;

function IcmpCreateFile: THandle; stdcall; external 'Iphlpapi.dll';
function IcmpCloseHandle(IcmpHandle: THandle): Boolean; stdcall; external 'Iphlpapi.dll';
function IcmpSendEcho(IcmpHandle: THandle; DestinationAddress: Cardinal; RequestData: Pointer; RequestSize: Word; RequestOptions: PIP_OPTION_INFORMATION; ReplyBuffer: Pointer; ReplySize: Cardinal; Timeout: Cardinal): Cardinal; stdcall; external 'Iphlpapi.dll';

function ResolveHost(Hostname: AnsiString): Cardinal;
var
  HostInfo: PHostEnt;
  T: ^PInAddr;
begin
  Result := inet_addr(PAnsiChar(Hostname));
  if Result = INADDR_NONE then begin
    HostInfo := gethostbyname(PAnsiChar(Hostname));
    if Assigned(HostInfo) then begin
      T := Pointer(HostInfo^.h_addr_list);
      if Assigned(T) and Assigned(T^) then
        Result := T^^.S_addr;
    end;
  end;
end;

function IsHostAlive(Hostname: String; pTripTime: PCardinal; Timeout, TTL: Integer): Boolean;
const
  SendBuffer: array[0..31] of AnsiChar = 'pingpongpingpongpingpongpingpong';
var
  WSA:    TWSADATA;
  Reply:  PICMP_ECHO_REPLY;
  Addr:   Cardinal;
  hIcmp:  THandle;
  Options: IP_OPTION_INFORMATION;
begin
  Result := False;
  FillChar(Options, SizeOf(IP_OPTION_INFORMATION), #0);
  Options.TTL := TTL;
  Options.TOS := 1;
  if WSAStartUp(((0 shl 8) + 2), WSA) = 0 then begin
    Addr := ResolveHost(AnsiString(Hostname));
    if Addr <> INADDR_NONE then begin
      hIcmp := IcmpCreateFile;
      if hicmp <> INVALID_HANDLE_VALUE then begin
        Reply := nil;
        try
          Reply := AllocMem(SizeOf(ICMP_ECHO_REPLY) + SizeOf(SendBuffer));
          IcmpSendEcho(hIcmp, Addr, @SendBuffer[0], SizeOf(SendBuffer), @Options, Reply, SizeOf(ICMP_ECHO_REPLY) + SizeOf(SendBuffer), Timeout);
          Result := Reply^.Status = 0;
          if Result and Assigned(pTripTime) then
            pTripTime^ := Reply^.RoundTripTime;
        finally
          IcmpCloseHandle(hIcmp);
          if Assigned(Reply) then
            FreeMem(Reply);
          WSACleanup;
        end;
      end;
    end else begin
      // Hostname konnte nicht aufgelöst werden.
      WSACleanup;
    end;
  end else begin
    // Winsock konnte nicht gestartet werden.
  end;
end;

end.
Delphi-Quellcode:
var
  RTT: Cardinal;
begin
  if IsHostalive('google.de', @RTT) then
    ShowMessage(IntToStr(RTT) + 'ms');
end;

Piro 12. Mär 2014 20:38

AW: IsHostAlive mit XE2 - Unklare Fehler / Warnungen
 
!!! VIELEN DANK !!!

Das hat geklappt, jetzt ist wieder alles erreichbar. Dieses Forum und seine Mitglieder sind der Hammer und haben mir schon mehr als einmal aus der Klemme geholfen.

Schönen Abend noch.

@himitsu : 1000 Danke nochmal

PeterPanino 28. Feb 2015 16:13

AW: IsHostAlive mit XE2 - Unklare Fehler / Warnungen
 
@ himitsu

IsHostalive('google.com', @RTT) gibt immer True zurück.

IsHostalive('microsoft.com', @RTT) gibt immer False zurück.

WARUM?

Delphi XE7

EDIT:

Wenn ich aber die IP-Adresse von microsoft.com (95.100.79.156) verwende, wird True zurückgegeben:

IsHostalive('95.100.79.156', @RTT) gibt immer True zurück.

Wieso funktioniert es also mit microsoft.com nicht?

Dalai 28. Feb 2015 16:34

AW: IsHostAlive mit XE2 - Unklare Fehler / Warnungen
 
Zitat:

Zitat von PeterPanino (Beitrag 1291869)
IsHostalive('google.com', @RTT) gibt immer True zurück.

IsHostalive('microsoft.com', @RTT) gibt immer False zurück.

WARUM?

Weil Google auf ICMP-Requests antwortet, Microsoft aber nicht. Letzteres ist übrigens typisch für die, denn standardmäßig antwortet kein Windows seit XP SP2 mehr auf ICMP-Requests, weil das in der Firewall (schwachsinnigerweise) abgeschaltet ist.

Zitat:

Wenn ich aber die IP-Adresse von microsoft.com (95.100.79.156) verwende, wird True zurückgegeben:

IsHostalive('95.100.79.156', @RTT) gibt immer True zurück.

Wieso funktioniert es also mit microsoft.com nicht?
Schau dir mal mit nslookup oder Webseiten wie IP2Geolocation an, auf welchen Namen die IP-Adressen auflösen, dann siehst du, dass hinter dieser IP Akamai steckt, nicht Microsoft (IP2Geolocation).

MfG Dalai

PeterPanino 28. Feb 2015 16:41

AW: IsHostAlive mit XE2 - Unklare Fehler / Warnungen
 
Zitat:

Zitat von Dalai (Beitrag 1291870)
... standardmäßig antwortet kein Windows seit XP SP2 mehr auf ICMP-Requests, weil das in der Firewall (schwachsinnigerweise) abgeschaltet ist.

Schutz gegen Port-Scans?

Kann ich aber sonst davon ausgehen, dass IsHostalive mit allen anderen "normalen" Domain-Namen IM INTERNET funktioniert?

PeterPanino 28. Feb 2015 17:04

AW: IsHostAlive mit XE2 - Unklare Fehler / Warnungen
 
Übrigens: Wenn ich IsHostalive mit einem leeren string aufrufe, gibt es immer True mit 0 ms zurück!

IsHostalive('', @RTT)

WARUM?

mjustin 28. Feb 2015 17:21

AW: IsHostAlive mit XE2 - Unklare Fehler / Warnungen
 
Zitat:

Zitat von PeterPanino (Beitrag 1291873)
Übrigens: Wenn ich IsHostalive mit einem leeren string aufrufe, gibt es immer True mit 0 ms zurück!

IsHostalive('', @RTT)

WARUM?

Weil die intern verwendete Funktion gethostbyname dann localhost verwendet.

Zitat:

If the name parameter points to an empty string or name is NULL, the returned string is the same as the string returned by a successful gethostname function call (the standard host name for the local computer).

Dalai 28. Feb 2015 17:24

AW: IsHostAlive mit XE2 - Unklare Fehler / Warnungen
 
Zitat:

Zitat von PeterPanino (Beitrag 1291872)
Zitat:

Zitat von Dalai (Beitrag 1291870)
... standardmäßig antwortet kein Windows seit XP SP2 mehr auf ICMP-Requests, weil das in der Firewall (schwachsinnigerweise) abgeschaltet ist.

Schutz gegen Port-Scans?

Schutz? Wenn ein Script-Kiddie mit automatisierten dumpfen Tools daherkommt, schützt das vielleicht. Aber doch nicht gegen Leute, die ernsthaft irgendwo Schaden anrichten wollen. Dagegen erschwert es - wie du nun selbst festgestellt hast - simpelste Diagnosen, weil ein Ping ins Leere läuft. Aber darüber kann man endlos diskutieren, und da es OT ist, belasse ich es dabei.

Zitat:

Kann ich aber sonst davon ausgehen, dass IsHostalive mit allen anderen "normalen" Domain-Namen IM INTERNET funktioniert?
Nö, weil manche Leute genau dieselbe Ansicht wie Microsoft vertreten und ICMPs verwerfen und nicht darauf antworten. Das kann man vorher nicht wissen. Die meisten antworten sauber auf Pings.

Zitat:

Zitat von PeterPanino (Beitrag 1291873)
Übrigens: Wenn ich IsHostalive mit einem leeren string aufrufe, gibt es immer True mit 0 ms zurück!

IsHostalive('', @RTT)

WARUM?

Keine Ahnung. Hast du mal durch den Code gesteppt mit verschiedenen übergebenen Strings/Domains? Aber ich sehe, da kam gerade noch eine andere Antwort dazwischen.

MfG Dalai

PeterPanino 28. Feb 2015 17:30

AW: IsHostAlive mit XE2 - Unklare Fehler / Warnungen
 
@mjustin Danke!

PeterPanino 28. Feb 2015 17:37

AW: IsHostAlive mit XE2 - Unklare Fehler / Warnungen
 
Danke auch an @himitsu! Ich habe jetzt 2 Tage lang vergeblich gesucht und probiert. Indy usw. Die von @himitsu bearbeitete Unit ist der erste Code, der auch dann verlässlich False zurückgibt, wenn ich das Kabel vom DSL-Router abgesteckt habe UND zugleich den Timeout-Wert verlässlich einhält!

PeterPanino 28. Feb 2015 17:41

AW: IsHostAlive mit XE2 - Unklare Fehler / Warnungen
 
@Dalai Man könnte das so testen: Wenn google.com antwortet, xyz.com aber gleichzeitig nicht, dann ist erwiesen, dass xyz.com ICMP-Pakete verwirft. Ist diese Schlussfolgerung richtig?

Dalai 28. Feb 2015 17:46

AW: IsHostAlive mit XE2 - Unklare Fehler / Warnungen
 
Zitat:

Zitat von PeterPanino (Beitrag 1291881)
@Dalai Man könnte das so testen: Wenn google.com antwortet, xyz.com aber gleichzeitig nicht, dann ist erwiesen, dass xyz.com ICMP-Pakete verwirft. Ist diese Schlussfolgerung richtig?

Nein. Man kann nicht unterscheiden, ob ein Host nicht auf ICMP-Requests antwortet oder ob er tatsächlich nicht erreichbar ist - jedenfalls nicht mit simplen Pings. Die Analyse dessen ist aufwendiger, z.B. mit traceroute (mit dem man auch nur eine ungefähre Aussage treffen kann), mit Requests an unterschiedliche Protokolle (HTTP, FTP, SSH, SMTP etc) uvm. Und dann spielen bei großen Unternehmen noch oft Load Balancer, mehrere IP-Adressen, und andere Dinge mit rein. Jede Thematik ist eben komplexer, wenn man genau arbeiten will ;).

MfG Dalai

PeterPanino 28. Feb 2015 19:46

AW: IsHostAlive mit XE2 - Unklare Fehler / Warnungen
 
Es gibt viele Fälle, in denen ich FuzzyLogic dem angestrebten Anspruch auf Perfektion (der in der Praxis doch nie ganz einlösbar ist) bewusst vorziehe, weil das auch der FuzzyLogic-Schnittstelle vieler User besser entspricht ...

Dalai 28. Feb 2015 20:03

AW: IsHostAlive mit XE2 - Unklare Fehler / Warnungen
 
Das mag sein. Im Falle eines nicht beantworteten Pings ist es aber nun einmal so, dass es tatsächlich 50:50 steht, ob er nicht beantwortet wird oder das Ziel tot ist - wenn man annimmt, dass die eigene Netzwerkverbindung und (bei einem Ziel im Internet) die Internetverbindung funktioniert. Es ist eben so.

Wobei letzteres noch nicht einmal der Fall sein muss, denn auch der Weg zum Ziel kann tot sein - oder vielleicht nur einer der Wege (deshalb können Webseiten auch nur für bestimmte Nutzer(gruppen) ausfallen oder nicht erreichbar sein). Fuzzy hin oder her, ein paar Fakten müssen schon geprüft werden, sonst sagt deine Software unter Umständen, dass der Host google.com tot ist, obwohl "nur" die eigene Internetverbindung nicht funktioniert. Dann mag das zwar auf diesen Host zutreffen, von dem aus geprüft wird, aber nicht auf alle anderen ;).

MfG Dalai


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:02 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz