ich habe den Eindruck, dass der Versand einer UPD-Nachricht per UDP.write("blabla");, an eine IP-Adresse die momentan nicht im lokalen Netzwerk vorhanden ist, den Rest des Codes blockiert.
UDP.write("blabla"); steht natürlich zwischen UDP.beginPacket(); und UDP.endPacket().
Warum ist dies so und was kann man gegen dieses Verhalten tun?
Ich dachte bisher eigentlich, dass es beim senden einer UDP-Nachricht vollkommen egal ist, ob sie ankommt, oder nicht, da es keinerlei Rückmeldungen gibt.
Das darf nicht blockieren. Beim Test, den Empfänger abgesteckt, sendet er fleißig weiter. Sobald der Empfänger wieder verfügbar ist, kommen ohne weiteres zutun die Daten wieder an.
Man kann auch nock vom Empfänger eine ACK Nachricht zurück schicken. Wenn das nicht ankommt, sendet der Sender solange er keine neueren Daten zum verschicken hat, immer wieder die Alten.
Poste mal den relevanten Code, oder doch besser den ganzen.
Ich kann die Schreie nach Code absolut verstehen, doch zum Einen ist mein Code auf mehreren Tabs verteilt (lösbar), aber zum Anderen wird auf Libraries zugegriffen, von denen vermutlich die Wenigsten Bock hätten sie sich zu laden. Somit würde es vermutlich auf eine unnötige Diskussion um Codebestandteile, welche nicht Gegenstand dieses Threads sein sollen hinauslaufen. Um dem entgegenzuwirken müsste ich den Code stark vereinfachen. Dies werde ich tun, falls keine einfache Lösung zum jetzigen Zeitpunkt greifbar scheint.
Chris72622:
Ich kann die Schreie nach Code absolut verstehen, doch zum Einen ist mein Code auf mehreren Tabs verteilt (lösbar), aber zum Anderen wird auf Libraries zugegriffen, von denen vermutlich die Wenigsten Bock hätten sie sich zu laden. Somit würde es vermutlich auf eine unnötige Diskussion um Codebestandteile, welche nicht Gegenstand dieses Threads sein sollen hinauslaufen. Um dem entgegenzuwirken müsste ich den Code stark vereinfachen. Dies werde ich tun, falls keine einfache Lösung zum jetzigen Zeitpunkt greifbar scheint.
Gruß Chris
Genau das tust du!
Und am besten nächstes mal sofort.
Jede Problemstelle einzeln testen!
Du sachst ja noch nicht mal welche Ethernetlib du verwendest, welchen Lan Controller....
Meine Glaskugel ist damit hoffnungslos überfordert!
Denn bei mir funktioniert UDP ohne zu blockieren.
Und ich möchte fast garantieren, dass es bei dir an ganz was anderem liegt.
Ich war nicht beim Bund, von daher verstehe ich den ersten Satz nicht.
Falls der ganze Code gewünscht wurde.. anbei ist er.
Es geht darum, dass der restliche Code ab und an stehenbleibt, sobald sich innerhalb von wamaState() Zustandswechsel ergeben und sich 192.168.0.21 nicht im Netzwerk befindet.
Arduino 1.6.5, Bounce2-Library, FSM-Library, Ethernet- und SPI-Libraries, wie sie mit Arduino "mitgeliefert" werden.
Chris72622:
Es geht darum, dass der restliche Code ab und an stehenbleibt, sobald sich innerhalb von wamaState() Zustandswechsel ergeben.
Kommt das UDP Paket an?
Wo bleibt der Code genau hängen? Weil in dem udp Teil der wamaState() sehe ich jetyt auf Anhieb nichts verkehrtes. Und wen das Paket ankommt, wurde bis UDP.endPacket(); korrekt abgearbeitet.
Chris72622:
ich habe den Eindruck, dass der Versand einer UPD-Nachricht per UDP.write("blabla");, an eine IP-Adresse die momentan nicht im lokalen Netzwerk vorhanden ist, den Rest des Codes blockiert.
UDP.write("blabla"); steht natürlich zwischen UDP.beginPacket(); und UDP.endPacket().
Warum ist dies so und was kann man gegen dieses Verhalten tun?
Du redest von irgendwas zwischen 1 bis 2 Sekunden, oder?
Das Verhalten und eine Blockierung in diesem Zeitrahmen ist bei ausgeschaltetem Empfänger normal.
Auch wenn UDP keinen Verbindungsaufbau zwischen Sender und Empfänger erfordert, so muß UDP doch wissen, in welche Richtung die Pakete losgeschickt werden müssen, damit sie auf eine solche "Route" geschickt werden, so dass sie den Empfänger überhaupt erreichen können.
Innerhalb desselben LANs wird glaube ich auch geprüft, ob der Empfänger überhaupt empfangsbereit ist, bevor ein UDP-Paket gesendet wird.
Ich glaube, dagegen kannst Du mit der existierenden Ethernet-Library wenig tun.
ja genau- ein bis zwei Sekunden kommen da schon mal zusammen.
Wenn es eine Möglichkeit gäbe die UDP-Nachrichten einfach so auf die Reise zu schicken, ohne dass der komplette Sketch angehalten werden würde, falls einer der Empfänger mal nicht erreichbar wäre, wäre das super. Ansonsten müsste ich mein komplettes Konzept überdenken.
Ich möchte die Lauffähigkeit dieses Sketches nicht davon abhängig machen, ob sich die zu besendenden "Außenstellen" im Netzwerk befinden oder nicht.
Bei mir wird der Sketch NICHT angehalten. Allerdings läuft es mit ESP8266 Modul als Sender, und da habe ich es explizit getestet.
Werde nun mal explizit einen Test mit einem MEGA und Ethernet Shield machen und den entsprechenden Empfänger abstecken.
Momentan broadcasted der MEGA an x.x.x.255 und es kommt überall an und er hängt auch nicht.
Chris72622:
Wenn es eine Möglichkeit gäbe die UDP-Nachrichten einfach so auf die Reise zu schicken, ohne dass der komplette Sketch angehalten werden würde, falls einer der Empfänger mal nicht erreichbar wäre, wäre das super.
Chris72622:
ja genau- ein bis zwei Sekunden kommen da schon mal zusammen.
Wenn es eine Möglichkeit gäbe die UDP-Nachrichten einfach so auf die Reise zu schicken, ohne dass der komplette Sketch angehalten werden würde, falls einer der Empfänger mal nicht erreichbar wäre, wäre das super. Ansonsten müsste ich mein komplettes Konzept überdenken.
Ich möchte die Lauffähigkeit dieses Sketches nicht davon abhängig machen, ob sich die zu besendenden "Außenstellen" im Netzwerk befinden oder nicht.
Wenn es Dich überhaupt nicht interessiert, ob Funktionsaufrufe nicht funktionieren und Fehler schmeißen, und Du daher Sendewiederholungen, Timeouts und Fehlerbehandlung zugunsten von schneller Abarbeitung über Bord werfen möchtest, hast Du schon mal überlegt, die Libraryfunktionen entsprechend abzuändern?
Beim Senden von UDP Packets wird offenbar am Ende diese Funktion in 'socket.cpp' aufgerufen:
int sendUDP(SOCKET s)
{
W5100.execCmdSn(s, Sock_SEND);
/* +2008.01 bj */
while ( (W5100.readSnIR(s) & SnIR::SEND_OK) != SnIR::SEND_OK )
{
if (W5100.readSnIR(s) & SnIR::TIMEOUT)
{
/* +2008.01 [bj]: clear interrupt */
W5100.writeSnIR(s, (SnIR::SEND_OK|SnIR::TIMEOUT));
return 0;
}
}
/* +2008.01 bj */
W5100.writeSnIR(s, SnIR::SEND_OK);
/* Sent ok */
return 1;
}
Ich würde mal aus dieser Funktion einfach die while-Schleife rausschmeißen, und dass die Funktion entweder 0 oder 1 als Rückgabewert liefern kann. Also ändern auf:
int sendUDP(SOCKET s)
{
W5100.execCmdSn(s, Sock_SEND);
/* +2008.01 bj */
W5100.writeSnIR(s, SnIR::SEND_OK);
return 1; /* Sent ok */
}
oder sogar:
int sendUDP(SOCKET s)
{
W5100.execCmdSn(s, Sock_SEND);
return 1; /* Sent ok */
}
Wie sieht es dann aus mit Funktionsfähigkeit und Zeitbedarf der Funktion?
Chris72622:
Bestehende Libraries abzuändern übersteigt für gewöhnlich meine Kenntnisse.
Auch wenn Du direkt einen konkreten Änderungsvorschlag für den Code bekommen hast, so wie in meinem letzten Posting?
Hinweis: Unter Windows könnte man mit Bordmitteln z.B. "write.exe" als Editor verwenden, um .cpp Dateien zu Editieren. Im Explorer rechte Maustaste und "Öffnen mit".
Chris72622:
Bin daher am überlegen, ob ich über regelmäßiges "Anpingen" die Problematik umgehen kann.
Beim Anpingen mußt Du aber sogar auf die Rückantwort des angepingten Netzteilnehmers warten, und dafür ein Timeout festlegen, wie lange Du warten möchtest.
Und selbst wenn Du beim Anpingen in Zeitabständen feststellst, dass ein Netzteilnehmer vorhanden ist: Da kann ja schon eine Millisekunde später der Netztstecker gezogen werden, und dann ist es wieder Essig mit UDP-Senden ohne Timeout-Delay.
Da rennt es nur so im seriellen Monitor, auch wenn ich den Empfänger ausschalte. Allerdings muss er EINMAL angeschaltet gewesen sein, sonst hast du die Pausen!
Sendest du an die .255 macht er keine Pause am Anfang, und die Infos können von JEDEM im lokalen Netz empfangen werden.