[C#] Ping -> Exception wenn Offline / Host nicht erreichbar

Cyperfriend

Der ohne Avatar
Registriert
14 Juli 2013
Beiträge
1.123
Folgender Code, soll prüfen, ob der Rechner online ist und wenn nicht alle 30 Sekunden prüfen, ob der Rechner dann online ist. Wenn ja soll der Timer gestoppt und das pingen eingestellt werden.

Zwei Dinge:
1) Wenn der Rechner offline bzw. der Host nicht erreichbar ist gibt es eine Exception. Warum und was kann getan werden? Wieso gibt "IPStatus.Success" nicht einfach "false" zurück und alles ist gut?

2) Abgesehen von der Exception: Funktioniert der Code so überhaupt? Ich frage nicht, ob er gut und professionell geschrieben ist, sondern nur, ob er so verwendet werden kann und von der Logik her stimmt.

[src=csharp]
string isOnline = "Offline";

public void testping()
{
timer1.Start();
if (timer1.Enabled == true)
{
Ping ping = new Ping(); // Soll alle 30 Sekunden ausgeführt werden, wenn Offline
PingReply pingReply = ping.Send("www.google.de"); // Exception wenn Offline :-(
if (pingReply.Status == IPStatus.Success == true) {
isOnline = "Online";
}
}
}

private void Form1_Load(object sender, EventArgs e)
{

// Timer aktivieren
timer1.Interval = 30000; // 30 Sekunden
timer1.Enabled = true;

// Prüfen, ob Computer online
testping();

if (isOnline == "Offline") {
testping();
} else {
lblIsOnline.Text = "Online";
timer1.Stop();
timer1.Enabled = false;
// Hier wird dann die Systemabfrage durchgeführt
}

lblStatusTimer.Text = timer1.Enabled.ToString();
[...][/src]
 
Zuletzt bearbeitet:
1) Für den Grund einer Exception müßte man die Art der Exception kennen. Also wie lautet diese?
Wie testest Du einen Offline-Host? Solltest Du da einfach einen nicht existierenden eintragen, dann ist der sicher offline, aber es knallt, weil er unbekannt ist.

2) Du benutzt den Timer ja gar nicht.



pingReply.Status == IPStatus.Success == true
 
Klingt erst einmal für mich als nicht C# Mensch seltsam. Die Docs sagen:
The Ping class does not throw this exception if the ICMP Echo request fails because of network, ICMP, or destination errors. For such errors, the Ping class returns a PingReply object with the relevant IPStatus value set in the Status property.

Scheint aber auch anderen zu passieren mit der Exception.

Exception wenn unbekannt und keine wenn bekannt aber nicht reagierend klingt für mich persönlich auch erstmal seltsam.
 
Wieso seltsam? Das sind beim Ping in der Konsole auch verschiedene Dinge.

Bei offline kommt da 'Antwort von xyz: Zielhost nicht erreichbar' und wenn der den Host nicht kennt 'Ping-Anforderung konnte Host "xyz" nicht finden.'

Beim c# Ping ist vergleichbar dann der IPStatus.Success false, oder es gibt bei unbekanntem Host eine System.Net.NetworkInformation.PingException (SocketException: Der angegebene Host ist unbekannt).
 
Ich meinte es ist seltsam, dass das eine eine Exception wirft und das andere nicht. Auf den zweiten Gedanken kann ich es dann aber doch nachvollziehen.
 
  • Thread Starter Thread Starter
  • #6
Also die Offlinefunktionalität teste ich indem ich kurzerhand das Netzwerkkabel ziehe.
Die Exception im Detail:
System.Net.NetworkInformation.PingException
HResult=0x80131509
Nachricht = Während einer Pinganforderung ist eine Ausnahme aufgetreten.
Quelle = System
Stapelüberwachung:
at System.Net.NetworkInformation.Ping.Send(String hostNameOrAddress, Int32 timeout, Byte[] buffer, PingOptions options)
at System.Net.NetworkInformation.Ping.Send(String hostNameOrAddress)
at Systeminfo.Form1.testping() in C:\Users\MarkVonPlay\source\repos\Systeminfo\Systeminfo\Form1.cs:line 63
at Systeminfo.Form1.Form1_Load(Object sender, EventArgs e) in C:\Users\MarkVonPlay\source\repos\Systeminfo\Systeminfo\Form1.cs:line 78
at System.Windows.Forms.Form.OnLoad(EventArgs e)
at System.Windows.Forms.Form.OnCreateControl()
at System.Windows.Forms.Control.CreateControl(Boolean fIgnoreVisible)
at System.Windows.Forms.Control.CreateControl()
at System.Windows.Forms.Control.WmShowWindow(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.Form.WmShowWindow(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

Diese Ausnahme wurde ursprünglich von dieser Aufrufliste ausgelöst:
System.Net.Dns.GetAddrInfo(string)
System.Net.Dns.InternalGetHostByName(string, bool)
System.Net.Dns.GetHostAddresses(string)
System.Net.NetworkInformation.Ping.Send(string, int, byte[], System.Net.NetworkInformation.PingOptions)

Innere Ausnahme 1:
SocketException: Der angegebene Host ist unbekannt

Wieso verwende ich den Timer nicht? Kurz meine Logik dazu:

In Zeile 2 initialisiere ich die variable "isOnline" und setze sie auf "Offline"
In Zeile 27 prüfe ich, ob "isOnline" auf "Offline" gesetzt ist. Beim ersten Durchlauf ist das logischerweise der Fall. Also führe ich die Funktion "testping" aus
Die Funktion "testping" prüft dann ob eine Internetverbindung besteht. In dem Fall, ob www.google.de erreichbar ist.
Wenn das der Fall ist wird die variable "isOnline" auf "Online" gesetzt. Wenn nicht bleibt die variable "isOnline" auf "Offline".
In Zeile 27 wird dann erneut geprüft, ob "isOnline" auf "Offline" gesetzt ist. Wenn das der Fall ist, wird wieder "testping" aufgerufen. Das wiederholt sich bis www.google.de erreichbar ist und "isOnline" auf "Online" gesetzt wird. Dann werden von Zeile 31-32 der Timer gestoppt und deaktiviert. testping wird nicht mehr aufgerufen

Bitte um Korrektur wenn ich da irgendwo falsch abgebogen bin.
 
Wenn Dein Rechner offline ist,kann er nicht abfragen welche Adresse Google hat. Aber auch mit einer IP käme es zu Fehlern, nicht nur unter .NET, sondern auch in der Windows-Eingabeaufforderung. Das ist also der falsche Weg zu testen.

In Zeile 27 prüfe ich, ob "isOnline" auf "Offline" gesetzt ist. Beim ersten Durchlauf ist das logischerweise der Fall. Also führe ich die Funktion "testping" aus
Das ist nicht logischerweise der Fall, weil Du ja bereits in 25 "testping" aufgerufen hast.

Was Du machst ist "testping" und bei Erfolg setzt Du den Labeltext auf online und gibst 2 unterschiedliche Befehle, die aber beide zum Ausschalten des Timers sind.
Bei Mißerfolg rufst Du einmal unmittelbar ein 2. Mal "testping", ohne dann aber noch weiteres zu tun.

In beiden Fällen setzt Du dann noch in einem weiteren Label ob der Timer an oder aus ist.

Warum Du den Timer nicht nutzt? Weil Du keinen Code hast, der darauf reagiert, wenn der Time ein Ereignis auslöst. (timer1_Tick)

Die Funktion "testping" prüft dann ob eine Internetverbindung besteht. In dem Fall, ob www.google.de erreichbar ist.

Das tut sie nicht. Wie oben erwähnt, funktioniert das nicht.

Ob Du Netzzugang hast, kannst Du mit var amIonline=NetworkInterface.GetIsNetworkAvailable(); prüfen.
 
  • Thread Starter Thread Starter
  • #8
NetworkInterface.GetIsNetworkAvailable() gibt immer "true" zurück, auch wenn ich das Netzwekkabel ziehe (Kein Wlan vorhanden) :unknown:

Recherchiere gerade, woran das liegt. Auf Anhieb nichts gefunden, suche weiter. Vielleicht ist ja hier jemand schneller.

Was das "IPStatus.Success" angeht: Irgendwie scheint mir das eine ziemlich sinnfreie Funktion zu sein, wenn diese nur funktioniert, wenn die Abfrage funktioniert und das Programm crasht, wenn das nicht der Fall ist.
 
Zuletzt bearbeitet:
Wieso sinnfrei? Das ist doch viel besser, als ohne Fehlermeldung.

Wenn der Ping nicht funktioniert kann es an Deiner Seite oder bei der Gegenstelle.
Jetzt mußt Du also weniger raten, woran es liegt.

Bei Einem Fehler liegt es wohl bei Dir, ist der Status false, ist die Gegenstelle wohl nicht erreichbar.

Wie hast Du denn NetworkInterface.GetIsNetworkAvailable() umgesetzt?
 
  • Thread Starter Thread Starter
  • #10
Naja:
[src=csharp] bool testonline = NetworkInterface.GetIsNetworkAvailable();
lblIsOnline.Text = testOnline.ToString();[/src]
 
Was das "IPStatus.Success" angeht: Irgendwie scheint mir das eine ziemlich sinnfreie Funktion zu sein, wenn diese nur funktioniert, wenn die Abfrage funktioniert und das Programm crasht, wenn das nicht der Fall ist.

So wie ich das verstehe wird nur eine Exception geworfen, wenn die angefragte Adresse nicht existiert. Das ist etwas anderes als wenn die gerade Offline ist. Die Annahme ist hierbei wohl, dass das Programm sich nur zu einer existierenden Stelle verbinden will. Die kann dann Online oder Offline sein, das sind quasi keine Ausnahmesituationen. Aber dass das Ziel gar nicht existiert, das wird ja im Regelbetrieb nicht so gedacht sein, d.h. es ist "exceptional", außergewöhnlich, etwas wovon ein Programm nicht ausgeht und muss daher eine Exception werfen.
 
  • Thread Starter Thread Starter
  • #12
So, ich habe den Code umgeschrieben und bis jetzt bin ich auch ein bisschen Stolz auf die Lösung, weil ich sie mir alleine ausgedacht habe und scheinbar auch funktioniert. Mal sehen, ob ich es hinterher, wenn ihr drüber geguckt habt immer noch bin :D.

[src=csharp] bool isOnline = false;

public void testping() {

try {
Ping ping = new Ping();
PingReply pingReply = ping.Send("www.google.de");
if (pingReply.Status == IPStatus.Success == true) {
isOnline = true;
}
} catch {
Thread.Sleep(10000); // 10 Sekunden nichts machen
}
}

private void Form1_Load(object sender, EventArgs e) {

while(isOnline == false) {
testping();
}

// Programm stoppt hier, solange Offline. Stimmt das?
// Wenn Online gehts hier automatisch weiter.
[/src]
 
Du behandelst also keine Fehler, sondern sorgst dafür, daß sich das Programm aufhängt und nur vielleicht weiter läuft, wenn sich die Bedingen derart geändert haben, daß vielleicht kein Fehler mehr auftritt.

Ob die (Dauer-)schleife jetzt einfach durchläuft oder immer wieder für 10 s mal anhält, macht da jetzt auch keinen Unterschied.




Wenn NetworkInterface.GetIsNetworkAvailable() bei Dir immer true ergibt, was ich von hier aus nicht erklären kann, dann gibt es da auch andere Möglichkeiten, um sicherzustellen, daß eine Netzwerkverbindung (nicht unbedingt Internetverbindung) besteht, was ja sonst einen Fehler auslöst.

Du könntest erst mal schauen, was Du in Deinem Gerät für Möglichkeiten für Verbindungen hast:

NetworkInterface[] interfaces =NetworkInterface.GetAllNetworkInterfaces();

Da sind dann alle Interfaces drin,Ethernet, Wlan etc.

Da kannst Du dann im Einzelnen mal nachschauen, für jedes networkInterface in interfaces:

var name = networkInterface.Name;
var type = networkInterface.NetworkInterfaceType;
var isUp = networkInterface.OperationalStatus == OperationalStatus.Up ? true : false;
 
  • Thread Starter Thread Starter
  • #14
Ja, Moment. Das Programm hängt sich nicht auf.
Ich habe das ja getestet. Wenn ich da in das catch ein "MessageBox.Show("Offline"); reinschreibe, kann ich das wegklicken so oft ich will. Die Box wird immer wieder erscheinen und erst, wenn Online, erscheint sie nicht mehr. Da eine Reaktion aber unnötig ist, lasse ich das Programm einfach gar nichts machen.
 
1) Im Code steht keine MessageBox
2) Eine MessageBox, die nicht weggeht, der User aus dem Programm heraus nicht weiter agieren kann, ist für mich auch ein hängendes Programm.
 
Zurück
Oben