C# Ping senden – Host-Erreichbarkeit ermitteln + Tipps in 2024

C# Ping senden - Onlinestatus ermitteln plus Bonus
C# Ping senden – Onlinestatus ermitteln plus Bonus

Einen C# Ping absenden, um den Onlinestatus zu ermitteln

Du möchtest in C# einen Ping absenden / absetzen, um die Erreichbarkeit eines Hosts oder eines Servers zu ermitteln? Dann bist Du im heutigen Beitrag genau richtig! Wir schauen uns hilfreiche und essenzielle Klassen, bzw. die notwendigen Zeilen Code dazu an.

infoDu benötigst nur einen kleines Codeschnipsel und hast keine Lust auf „blabla“? Navigiere dazu einfach zum schnellen Beispiel, oder verwende das Inhaltsverzeichnis. Selbstverständlich habe ich auch VB.NET-Schnipsel hinzugefügt.

Zusätzlich erkläre ich noch ein paar Feinheiten / füge Tipps hinzu, aber das wirst Du ja dann gleich sehen. Wie Du sicherlich aus verschiedenen Videos weißt, lege ich viel Wert auf sauberen Code. Dazu gibt es besonders im „finalen Beispiel“ detaillierte Informationen.

Der Code sollte daher (wie immer):

  • wartbar
  • wiederverwendbar
  • und einfach zu lesen sein.

Was ist überhaupt ein „Ping“?

Was ist ein Ping überhaupt? – C# Ping
Was ist ein Ping überhaupt? – C# Ping

Bevor wir uns anschauen, wie ein Ping in C# versendet wird, werfen wir zuerst einen Blick darauf, was ein Ping überhaupt ist. Natürlich kannst Du diese Sektion überspringen, wenn Du schon einiges über die Erreichbarkeitsprüfung, Latenzmessung, Fehlerdiagnose, usw. weißt.

Schaue Dir zum besseren Verständnis einmal das obige Bild an. Dort siehst Du, dass ein Gerät A eine Nachricht mit dem Inhalt „Bist Du da?“ an Gerät B sendet (oranger Pfeil). Das Gerät B Antwortet dann mit einer Nachricht und dem Inhalt „Ja, ich bin da!“ (grüner Pfeil).

Ich versuche an dieser Stelle nicht zu tief in das technische Thema zu tauchen, aber zumindest die wichtigsten Dinge anzuschneiden.

Analog zu der obigen Darstellung im Bild, kann Gerät A nun festhalten:

  • wann es die Nachricht rausgesendet hat,
  • ob eine Antwort vom Gerät B kam
  • und wie lange die Antwort gedauert hat

Je nachdem wie streng / genau man es definieren möchte, könnte man also sagen:

Ein Ping ist eine Nachricht, Welche an einen Empfänger gesendet und von der anschließend eine Antwort „erwartet“ wird. Aus dieser Anfrage-Antwort-Abfolge kann man dann verschiedene Informationen, wie die z. B. benötigte Dauer ablesen. Natürlich kann ein Ping auch „abgelehnt“, bzw. das Ziel nicht erreicht werden.

In der Befehlszeile vom Betriebssystem

Pings können typischerweise einfach über die betriebssystem-internen Befehlszeile abgesendet werden. Dazu öffnen wir z. B. unter Windows die Kommandozeile mit „Windowstaste“ und tippen anschließend „cmd“.

Windows CMD / Befehlszeile öffnen
Windows CMD / Befehlszeile öffnen

Nachdem sich die Kommandozeile nun geöffnet hat, können wir einen beispielhaften Ping absenden. Dies funktioniert – wer hätte es gedacht – mit dem „ping“-Befehl. Wir tippen also den „ping“-Befehl in die Konsole und fügen noch einen Ziel-Host hinzu:

Windows CMD Ping Befehl Ausgabe
Windows CMD Ping Befehl Ausgabe

Ich würde sagen, wir sind nun beim „Warum“ der Ping-Nachrichten angekommen. Das schauen wir uns in der nächsten Sektion an. Man einige Aspekte vermutlich schon aus der obigen Ausgabe antizipieren, aber gut – schauen wir uns das Ganze einmal im Detail an.

Warum Pings senden?

Warum sollte oder könnte man C# Pings senden?
Warum sollte oder könnte man C# Pings senden?

Nachdem wir nun verstanden haben, was ein Ping im Groben ist, schauen wir nun auf den Programmier-Aspekt, bzw. das „Warum“ allgemein. Stelle Dir vor, Du hast Dir eine kleine, grafische Oberfläche zusammengebaut. Diese soll eine Liste von Geräten aufführen und ob Diese erreichbar sind / waren.

Im Endeffekt können wir diese Vorgehensweise, bzw. das Tool als eine Art „Diagnose“-Tool festhalten. Genauer vielleicht „Netzwerkdiagnose“, denn Du möchtest ja schauen – diagnostizieren – was so in Deinem Netzwerk passiert / erreichbar ist. Genau dafür eignet sich ein Ping!

Erreichbarkeitsprüfung

Wie oben schon im Beispiel angeschnitten, eignet sich ein Ping etwa, um festzustellen, ob ein bestimmter, sogenannter „Host“ erreichbar ist. Die Erfolgsmeldung des Pings bedeutet, dass das Ziel – also der Host – erreichbar war.

warningWichtig: Nur weil ein Ping nicht erfolgreich war, heißt es nicht, dass ein Host zwangsweise „offline“ ist! Der Host kann selbst entscheiden, ob er auf derartige Nachrichten Antworten möchte.

Latenzmessung

Neben der Erreichbarkeit an sich, gibt der Ping uns noch weitere diagnostische Informationen. Darunter: Wie lange es gedauert hat, bis das Nachrichten-Paket beim Host ankam und wir eine Nachricht zurückerhalten haben. Oder kurzum: Die Latenz, also der Zeitbedarf für das „Hin-und-Her“.

Allgemein bezeichnet man diese Zeit auch als „Round-Trip Time“, kurz „RTT“. Schaue Dir dazu ggf. auch noch einmal das Bild von oben an. Dort wird (ich vermute es jetzt einfach mal) klar, warum die „RTT“ so genannt wurde.

Fehlerdiagnose

Vor allem während des Aufbaus eines Netzwerk, oder bei dessen späterer Überwachung, können Pings helfen. So könnte man etwa prüfen, ob Geräte im Netzwerk korrekt konfiguriert und somit unter der korrekten IP erreichbar sind.

Dazu gibt es verschiedene Vorgehensweisen, darunter, meist eine Art Endlos-Ping, oder etwa die Versendung von Anzahl-basierten Pings. Ich könnte also eine gewisse Zeit lang einen Ping an einen Host senden, um die Verbindungsstabilität zu diagnostizieren. Falls ich eine Art permanente Überwachung wünsche, könnte ich dies dementsprechend auch konfigurieren.

Schnelle Beispiele für einen C# Ping

Schnelle C# Ping Beispiele
Schnelle C# Ping Beispiele

Du brauchst nur ein schnelles Beispiel? Keine Sorge, dafür habe ich auch gesorgt! Ich finde es nur immer wichtig, auch ein wenig „Behind the scenes“-Informationen zu haben. Sonst versteht man häufig nicht, was man da eigentlich macht, bzw. bekommt Probleme, wenn eine Kleinigkeit schief geht.

Hier ist ein kurzer und typischer Beispielcode für einen C# Ping (VB.NET habe ich auch dazu gepackt…).

Die einfachste Variante

Um überhaupt einen Ping senden zu können, müssen wir die „Ping“-Klasse des „System.Net.NetworkInformation“-Namespaces importieren. Das passiert – wie üblich – im Datei-Kopf. Danach erstellen wir eine Variable, Welche den anzupingenden Host beinhaltet. In diesem Beispiel ist das „google.de“.

Natürlich könnten wir hier auch einfach eine andere IP verwenden. Im nächsten Schritt erstellen wir eine neue Instanz (Objekt) der Ping“-Klasse. Nun rufen wir im letzten Schritt die „Send“-Methode des erstellten „Ping“-Objekts auf.

Fertig, oder!? Nicht ganz! Wir müssen die Antwort schließlich noch auswerten, sonst hat es nicht ganz so viel gebracht. Aber es kommt sowieso noch „mehr“ weiter unten :).

// ganz oben...
using System.Net.NetworkInformation;

// irgendwo, wo's ausgeführt werden kann
// in einer Methode
var host = "google.de";
var ping = new Ping();
var reply = ping.Send(host);

// mach was mit dem Reply
' ganz oben...
' Imports System.Net.NetworkInformation

' irgendwo, wo's ausgeführt werden kann
' in einer Sub, oder Ähnlichem
Dim host = "google.de"
Dim ping = New Ping()
Dim reply = ping.Send(host)

' mach was mit dem Reply

Etwas besser, mit Catch und Auswertung

Grundsätzlich ist das vorherige Beispiel schon ganz gut. Es beschreibt die grundlegenden Schritte, mangelt aber ein wenig an „Bulletproof“-Code. Besonders bei der Arbeit mit Netzwerken kann es ziemlich schnell zu Fehlern, also „Ausnahmen“ (engl. Exceptions) kommen. Diese sollten selbstverständlich sauber abgefangen werden.

Normalerweise bin ich kein Fan von „Vorschlaghammer-Try-Catches“, also Fehlerbehandlungen, Die einfach nur den fehlerbehafteten Code ummanteln und praktisch alles „in one Go“ abfangen. Ich denke allerdings, dass es hier durchaus okay ist.

Dazu packen wir den kritischen Code – wie üblich – in eine Fehlerbehandlung. Hierbei sollte es das Absenden des Pings selbst sein, jedoch nicht die Erstellung (vergiss nicht den Import von oben…). Ebenso benutzen wir dieses Mal eine Funktion / Methode, Die man später wiederverwenden könnte.

// für die Ping-Klasse selbst
using System.Net.NetworkInformation;
// für die Exception-Klasse
using System;

// wiederverwendbare Funktion
private bool TryPingHost(string host)
{
  var ping = new Ping();

  try {
    // der kritische Code
    var reply = ping.Send(host);
    return reply.Status == IPStatus.Success;
  } catch (Exception ex) {
    return false;
  }
}

// Aufruf
var pingWasSuccessful = TryPingHost("google.de");

// Auswertung
if (pingWasSuccessful) {
  // mach' was, wenn erfolgreich
} else {
  // mach' was, wenn NICHT erfolgreich
}
' für die Ping-Klasse selbst
Imports System.Net.NetworkInformation
' für die Exception-Klasse
Imports System

' wiederverwendbare Funktion
Private Function TryPingHost(host As String) As Boolean
    Dim ping = New Ping()

    Try
        Dim reply = ping.Send(host)
        Return reply.Status = IPStatus.Success
    Catch ex As Exception
        Return False
    End Try
End Function

' Aufruf
Dim pingWasSuccessful = TryPingHost()

' Auswertung
If pingWasSuccessful Then
  ' mach' was, wenn erfolgreich
Else
  ' mach' was, wenn NICHT erfolgreich
End If

Letzte Feinschliffe – C# Ping Endlevel

Das Ping Endlevel
Das Ping Endlevel

Nun würde ich noch 1-2 weitere Verbesserungen vorstellen wollen. Obwohl die beiden Beispiele schon viel mit sich bringen, könnten wir nun ins „Endlevel“ durchstarten. Bisher haben wir leider keine asynchrone Durchführung des C# Pings. Das könnte dazu führen, dass die Oberfläche einfriert – was man heutzutage natürlich absolut nicht mehr haben möchte.

Bauen wir also nun eine asynchrone Variante des Pings, ggf. sogar direkt mit einer abstrakteren Form. Eine, wo wir den Code wirklich sauber mit Schnittstellen (Interfaces) flexibel gestalten können. Dies fördert die oben schon angesprochene Wartbarkeit und Flexibilität von Programmen.

Ich bitte also noch ein letztes Mal um Deine Aufmerksamkeit :)!

Abstraktion

Lass uns nun einmal den Ablauf abstrahieren. Das hilft uns dabei, die wichtigen Bestandteile / Eigenschaften zu separieren und unseren Code auf das Wesentliche zu fokussieren. Was brauchen wir eigentlich?

Man könnte sagen, dass wir einen Netzwerk-Service brauchen, Welcher uns gewisse Informationen liefert. Um genau zu sein: Einen Service, der in der Lage ist, uns die Information zu geben, ob ein Host erreichbar ist.

Lass uns das also genau so definieren – und das macht man mit Interfaces. Dabei ist es uns ja egal, wie dieser (oder ein anderer) jeweiliger Service nachher den „Ping“ implementiert. Man könnte z. B. einen Test-Service haben, der nur so tut, als würde er wirklich nach außen „telefonieren“.

Nun aber zuerst das Interface / die Schnittstelle – beachte, dass ich die Methode umbenannt habe. Ebenso benutzen wir das .NET-typische „Async“-Suffix.

using System.Threading.Tasks;

    /// <summary>
    /// An interface, denoting something which is able to provide network based operations
    /// </summary>
    public interface INetworkService
    {

        /// <summary>
        /// Tries to send a ping request to the specified <paramref name="host"/>
        /// </summary>
        /// <param name="host">The host to be pinged</param>
        /// <returns>True, if the host could be reached and we got a successful signal, false otherwise.</returns>
        Task<bool> TryPingHostAsync(string host);

    }
Imports System.Threading.Tasks

''' <summary>
''' An interface, denoting something which is able to provide network based operations
''' </summary>
Public Interface INetworkService

    ''' <summary>
    ''' Tries to send a ping request to the specified <paramrefname="host"/>
    ''' </summary>
    ''' <paramname="host">The host to be pinged</param>
    ''' <returns>True, if the host could be reached and we got a successful signal, false otherwise.</returns>
    Function TryPingHostAsync(host As String) As Task(Of Boolean)

End Interface

Eine mögliche, asynchrone Implementierung

Beachte, dass ich hier die „ConfigureAwait(false)“-Anweisung verwende. Damit verhindere ich potenziell sinnloses „Context-Hopping“. Gerne kannst Du in meinem Blogpost über „ConfigureAwait“ mehr dazu erfahren.

Nun aber den Fokus auf unsere Implementierung des Interfaces / der Schnittstelle. Ich lasse nun die Imports weg, damit das nicht so viel sinnlosen Platz zieht. Denke aber bitte daran, Diese durchzuführen!

Ich habe dem Code auch ein wenig an Dokumentation hinzugefügt. Nun bist Du Unit-Test ready und kannst den Code auch einfacher mit Hilfe von Dependency Injection verwenden. Lies gerne den diesbezüglichen Beitrag, falls Du nicht viel mit „Dependency Injection“, kurz „DI“ anfangen kannst.

/// <inheritdoc/>
public class NetworkService : INetworkService
{

    /// <inheritdoc/>
    public async Task<bool> TryPingHostAsync(string host)
    {
        var ping = new Ping();
        try
        {
            var reply = await ping
                .SendPingAsync(host)
                .ConfigureAwait(false);
            return reply.Status == IPStatus.Success;
        }
        catch (Exception)
        {
            return false;
        }
    }

}
''' <inheritdoc/>
Public Class NetworkService
    Inherits INetworkService

    ''' <inheritdoc/>
    Public Async Function TryPingHostAsync(host As String) As Task(Of Boolean)
        Dim ping = New Ping()
        Try
            Dim reply = Await ping _
                .SendPingAsync(host) _
                .ConfigureAwait(False)
            Return reply.Status = IPStatus.Success
        Catch ex As Exception
            Return False
        End Try
    End Function

End Class

Verwendung

So, nun sind wir am Ende angekommen und können den Code verwenden. Dazu erstellst Du einfach eine Instanz der „NetworkService“-Klasse (oder wie auch immer Du Sie genannt hast). Danach kannst Du Ihre „TryPingHostAsync“-Methode aufrufen und den resultierenden Boolean überprüfen.

In einer professionellen / „echten“ Anwendung sollte die Instanziierung natürlich über eine Art „Dependency Injection Container“ erfolgen. Das hängt aber mit Deinem Projektaufbau zusammen :)!

Hier der finale Code (Aufruf):

var networkService = new NetworkService();

// async
var wasPingSuccessful = await networkService.TryPingHostAsync("google.de");

// sync
var wasPingSuccessful = networkService.TryPingHostAsync("google.de").Result;

// ...
Dim networkService = New NetworkService()

' async
Dim wasPingSuccessful = Await networkService.TryPingHostAsync("google.de");

' sync 
Dim wasPingSuccessful = networkService.TryPingHostAsync("google.de").Result

' ...

Fazit – C# Ping senden

Im heutigen Beitrag habe ich Dir gezeigt, wie Du einen C# Ping absendest, bzw. Du das Ergebnis davon auswertest. Ein wichtiger Aspekt war natürlich auch, was ein Ping überhaupt ist. Zusätzlich haben wir uns angeschaut, welche potenziellen Gründe es für die Nutzung eines Pings gibt. Am Ende haben wir dann im Sinne von „Clean Code“ eine vernünftige Abstraktion + Implementierung eingeführt.

Natürlich kannst Du hier alles Deinen individuellen Bedürfnissen anpassen. Falls Du ein wenig überfordert bist, schaue gerne in die folgende Download-Sektion. Dort kannst Du Dir die Beispiele herunterladen und ganz easy „Am Mann“ (oder Frau) ausprobieren!

Downloads

Hier findest Du die Downloads mit den Beispielcodes aus diesem Projekt. Damit ist es manchmal einfacher, den ganzen Kram zu verstehen. Ist ja nun einmal gar nicht so wenig, wenn man alles etwas tiefer verstehen und sauber umsetzen möchte.

Hierbei ist es natürlich relativ egal, ob man eine WPF oder Windows Forms Anwendung verwendet. Ist nur ein Beispiel :).

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert