hi ich verwende lwIP mit der socket API Ich bin client und rufe Daten von einem Server ab Gibt es eine Möglichkeit eine fehlerhafte Verbindung schneller zu erkennen? man kann zwar die TCP_SYNMAXRTX retries kürzen um etwas schneller zu reagieren, ist aber auch evtl unschön. Also wie kann man relativ schnell eine Fehlerhafte verbindung erkennen? SO_RCVTIMEO, SO_SNDTIMEO wird genutzt verkürzt aber nicht das SYN Timeout. danke
:
Verschoben durch Moderator
Definiere "fehlerhafte Verbindung." TCP (RFC793) definiert über Zustandsmachinen relativ genau, wie ein Stack zu reagieren hat. Zu unterscheiden sind hier speziell Nichtreagieren des Servers (per Default sehr langer Timeout) gegenüber Nichtverfügbarkeit des Servers (RST Paket serverseitig, kommt in der Regel schnell zurück). Die einzige Möglichkeit, im ersteren Fall schneller als der mehrminütige Wartezeit informiert zu werden ist über non blocking connects.
hi Es ist der Fall: Server offline Es kommt also keine antwort vom Server. werde mal nach "non blocking connects" suchen danke
Stichwort O_NONBLOCK in lwip. Gern geschehen!
:
Bearbeitet durch User
danke nochmal mit
1 | int opt = 1; |
2 | ret = lwip_ioctl( stream->sock , FIONBIO, &opt); |
3 | ret = connect( ... ); |
4 | |
5 | ...
|
6 | |
7 | ret = lwip_select( ... ); |
8 | ...
|
funktioniert das recht gut
ztr schrieb: > Es ist der Fall: Server offline > Es kommt also keine antwort vom Server. Normalerweise kommt dann vom Router oder vom Netz (im LAN) die Antwort: "Keiner zu Hause" (Address unreachable) relativ schnell. Wenn keine Atwort kommt muss der Server eigentlich AN sein. Manche Firewalls haben da aber leider eigene Vorstellungen.
Jim M. schrieb: > ztr schrieb: >> Es ist der Fall: Server offline >> Es kommt also keine antwort vom Server. > > Normalerweise kommt dann vom Router oder vom Netz (im LAN) die Antwort: > "Keiner zu Hause" (Address unreachable) relativ schnell. > Ausser die Zielmaschine liegt im selben Subnetz, dann gibt es Niemanden, der das übernehmen kann... es ist enorm schwierig, hier generell Aussagen zu machen, weil Netzwerkinfrastruktur enorm heterogen ist (wie Du schon selber schreibst).
Ruediger A. schrieb: > Ausser die Zielmaschine liegt im selben Subnetz, dann gibt es Niemanden, Dann schlägt ARP Timeout zu. Mach mal ein "ping" auf eine nicht existierende Addresse im LAN, das kommt nach wenigen Sekunden als "nicht erreichbar" zurück.
Jim M. schrieb: > Normalerweise kommt dann vom Router oder vom Netz (im LAN) die Antwort: > "Keiner zu Hause" (Address unreachable) relativ schnell. > > Wenn keine Atwort kommt muss der Server eigentlich AN sein. Manche > Firewalls haben da aber leider eigene Vorstellungen. ich bin leider lokal im LAN mit festen IPs ohne router. es besteht zwar auch die möglichkeit .. die geräte sollen aber grundsätzlich alleine agieren
ztr schrieb: > ich bin leider lokal im LAN mit festen IPs ohne router. > es besteht zwar auch die möglichkeit .. > die geräte sollen aber grundsätzlich alleine agieren Tja, dann kannst du nur regelmäsig per ICMP- Pings fahren, denn der Server wird sich nicht bei dir melden wenn er offline geht. Wie das in IwIP realisiert wird weiß ich leider nicht
Jim M. schrieb: > Ruediger A. schrieb: >> Ausser die Zielmaschine liegt im selben Subnetz, dann gibt es Niemanden, > > Dann schlägt ARP Timeout zu. Mach mal ein "ping" auf eine nicht > existierende Addresse im LAN, das kommt nach wenigen Sekunden als "nicht > erreichbar" zurück. Mach mal ein "ping -w 10000" auf eine nicht existierende Addresse in deinem Subnetz, das kommt bei meinem Rechner nach 10 Sekunden zurück. Das hat mit ARP nichts zu tun, das ist ein icmp Timeout. Ob ein icmp Destination Unreachable dazwischen kommt (der u.A. als Reaktion auf ein ARP request timeout generiert werden kann) und den icmp Timeout verkürzt, ist sehr stark konfigurationsabhängig. Destnation Unreachable kann auch administrativ unterdrückt werden.
Mit der obigen Lösung funktioniert das recht gut. Das verkürzt das Timeout auf vom mir gesetzte 2s. Das ist für mich OK. Alles andere ( ICMP vorweg usw) wäre momentan zu Aufwendig um den bestehenden Code zu ändern. Ist aber als Idee vermerkt!! Habe das Problem wenn ich das Bild einer IP Kameras abrufen möchte aber die Kamera nicht da ist( reset/defekt ... ) . Ich möchte dann nicht ewig warten bis die 12 SYN( lwIP default ) Anfragen raus sind. So weiß ich nun nach 2s das keine Antwort kam und gehe davon aus das Gerät ist momentan nicht da.
hi ich nochmal Was funktioniert: Erkennen eines fehlers beim Verbindungsaufbau. Nach max 2 sek steht der stream oder er ist fehlerhaft. Der Teil funktioniert soweit. Was aber leider nicht erkannt wird: Wird bei einem laufenden Stream das Kabel des Servers aus dem switch gezogen, wird kein Fehler erkannt. Select kommt immer mit einem return von 0 und getsockopt bemerkt hier auch keinen fehler. Wie kann man also eine verlorene Verbindung erkennen? Der untere Teil funktioniert zumindest soweit zuverlässig das sich nichts aufhängt. Man kann problemlos den socket schließen und ggf neustarten. zum Lesen vom socket nutze ich auch das select.
1 | fd_set readset, errset; |
2 | FD_ZERO(&readset); |
3 | FD_ZERO(&errset); |
4 | FD_SET(stream->sock, &readset); |
5 | FD_SET(stream->sock, &errset); |
6 | struct timeoutval interval = { 1000 / 1000, (uint32_t) (1000 % 1000) * 1000 }; |
7 | int ret = lwip_select(stream->sock+1 , &readset, NULL , &errset, &interval); |
8 | |
9 | if( ret < 0 ) |
10 | {
|
11 | goto out; |
12 | }
|
13 | else
|
14 | {
|
15 | int opt; |
16 | int lon = sizeof(int); |
17 | getsockopt(stream->sock, SOL_SOCKET, SO_ERROR, (void*)(&opt), (socklen_t*)&lon); |
18 | if (opt) { |
19 | goto out; |
20 | }
|
21 | if (FD_ISSET(stream->sock, &readset)) |
22 | {
|
23 | int rxlen = lwip_recv( stream->sock, stream->rxbuf, STREAM_BUFFSZ , 0 ); |
24 | if( rxlen < 0){ |
25 | goto out; |
26 | }else if( rxlen >= 0){ |
27 | ...
|
28 | }
|
29 | }else if (FD_ISSET(stream->sock, &errset)){ |
30 | goto out; |
31 | }
|
32 | }
|
Das ginge über das link up/link down interface. Allerdings ist es vergebene Lebensmühe. Damit erkennst Du nur den ersten Schritt der physikalischen Verbindung, also den link pulse zum Router. Wenn Jemand den Router ausstöpselt oder der Provider einen Ausfall hat oder Jemand in deinem Zielnetz eine Firewall ínstalliert, die einseitig Verbindungen zumacht, merkst Du nichts davon. Oder oder oder. Die Netzwerkwelt ist viel zu heterogen, als dass Du eine in Allen Fällen sichere Lösung implementieren kannst, die Alles abdeckt. Du musst auf Applikationsebene Timeouts, Lifechecks und ACKs nutzen, um das Protokoll sauber zu kriegen. Verlass Dich NIEMALS auf die unterliegende Netzwerkinfrastruktur.
ztr schrieb: > Wie kann man also eine verlorene Verbindung erkennen? http://tldp.org/HOWTO/TCP-Keepalive-HOWTO/overview.html
Ruediger A. schrieb: > Das ginge über das link up/link down interface. > > Allerdings ist es vergebene Lebensmühe. Damit erkennst Du nur den ersten > Schritt der physikalischen Verbindung, also den link pulse zum Router. > Wenn Jemand den Router ausstöpselt oder der Provider einen Ausfall hat > oder Jemand in deinem Zielnetz eine Firewall ínstalliert, die einseitig > Verbindungen zumacht, merkst Du nichts davon. Oder oder oder. > > Die Netzwerkwelt ist viel zu heterogen, als dass Du eine in Allen Fällen > sichere Lösung implementieren kannst, die Alles abdeckt. Du musst auf > Applikationsebene Timeouts, Lifechecks und ACKs nutzen, um das Protokoll > sauber zu kriegen. Verlass Dich NIEMALS auf die unterliegende > Netzwerkinfrastruktur. Es geht eher ob die Gegenstelle die "weg" sein kann. Nicht mein Gerät. c-hater schrieb: >> Wie kann man also eine verlorene Verbindung erkennen? > > http://tldp.org/HOWTO/TCP-Keepalive-HOWTO/overview.html Das hilft mir schon weiter ... Muss mal schauen in wieweit man das nutzen kann ... Es funktioniert jetzt so das der stream eben abbrechen kann aber nichts böses passiert. Das ist schon mal viel wert. eine Erkennung wäre hier noch im vorteil
ztr schrieb: > Ruediger A. schrieb: >> Das ginge über das link up/link down interface. >> >> Allerdings ist es vergebene Lebensmühe. Damit erkennst Du nur den ersten >> Schritt der physikalischen Verbindung, also den link pulse zum Router. >> Wenn Jemand den Router ausstöpselt oder der Provider einen Ausfall hat >> oder Jemand in deinem Zielnetz eine Firewall ínstalliert, die einseitig >> Verbindungen zumacht, merkst Du nichts davon. Oder oder oder. >> >> Die Netzwerkwelt ist viel zu heterogen, als dass Du eine in Allen Fällen >> sichere Lösung implementieren kannst, die Alles abdeckt. Du musst auf >> Applikationsebene Timeouts, Lifechecks und ACKs nutzen, um das Protokoll >> sauber zu kriegen. Verlass Dich NIEMALS auf die unterliegende >> Netzwerkinfrastruktur. > > Es geht eher ob die Gegenstelle die "weg" sein kann. > Nicht mein Gerät. > Du machst hier denselben Denkfehler wie sehr viele Andere auch. Dein Client kann nicht 100% wissen, was der Grund für eine Kommunikationsstörung mit seinem Server ist. Es kann sehr viel Gründe geben, z.B. 1. physikalischer Link des Ethernets weg (s.o.). 2. logischer link weg (Netzwerk hinter dem Router gestört) 3. IP Adress Konflikte/NAT Probleme 4. Namensauflösungsprobleme, falls Server mit DynDNS o.ä, angesprochen wird 5. Störungen im Netz (Schluckauf, längere delays als gewohnt o.ä.) 6. Server nicht mehr erreichbar 7. Server hat Abbruch nicht erkannt und nimmt zwar die Verbindung an, erlaubt aber keine Kommunikation mehr (falls es ein single threaded server ist) 8. Auf dem Server ist momentan der Service nicht verfügbar, oder eine Firewall hängt dazwischen und verbietet den Service etc pp. Abhängig von der konkreten Netzwerkkonfiguration in einer gegebenen Installation können keine, mehrere oder jede Kombination dieser und Anderer hier nicht genannter Probleme aufdecken. Dein Client kann nicht all diese Ursachen individuell abdecken, voneinander unterscheiden oder differenziert darauf eingehen. Das ist auch nicht Sinn und Zweck von TCP/IP. Das Einzige was Du machen kannst (und musst) ist dafür sorgen, dass jedes dieser möglichen Probleme deterministisch abgehandelt wird. Dazu gibt es Lifechecks (das kannst Du entweder über keepalive deinem TCP stack überlassen oder auf Applikationsebene selber abhandeln. Für beide Optionen gibt es sinnvolle Anwendungen) und Timeouts. Ausserdem sollte dein Applikationsprotokoll durch Telegrammbestätigungen zwischen Client und Swerver synchronisieren. Eine Falle in die Leute gerne tappen ist z.B. ein send() abzusetzen und den Returnwert nicht auszuwerten (und bei >0 nicht zwischen == requestsize und < requestsize zu unterscheiden). Aber Vorsicht: Ein Returnwert von -1 heisst nicht zwangsweise Verbindungsabbruch, sondern mglw nur, dass nicht mehr genügend Platz im Ausgangspuffer ist. Kannst Du selber simulieren: Bau eine Verbindung zwischen zwei Maschinen auf, schicke ein paar Pakete hin und her, dann ziehe das Kabel am Server ab und setze weiter ein paar send() Pakete ab. Du kriegst so lange Erfolg zurück, wie im Ausgangspuffer noch Platz ist, dann einen Fehler. Steckst Du den Server dann wieder ein (und der hat den fehlenden link nicht als Grund zum Verbidnungsabbruch genommen), arbeitet er plötzlich alle in der Zwischenzeit angefallenen Pakete ab und schickt Dir mglw. einen Haufen ACKs. Wenn Du dann den Fehler gemacht hast, retransmission timeouts aber keine Paketsequenznummern im Protokoll vorzusehen, werden dann mglw. die ACKs falschen Paketen zugeordnet. Protokolldesign im Netz hat viele Fallstricke. Ich habe in den 20 Jahren, in denen ich das professionell mache, bereits viele davon erlebt, aber es bleibt immer spannend. <Achtung Eigenwerbung>: In Kapitel 7 meines Buches gehe ich relativ ausführlich auf mehrere dieser Fallen ein.
Ruediger A. schrieb: > Du machst hier denselben Denkfehler wie sehr viele Andere auch. garantiert ! Ruediger A. schrieb: > Protokolldesign im Netz hat viele Fallstricke. Ich habe in den 20 > Jahren, in denen ich das professionell mache, bereits viele davon > erlebt, aber es bleibt immer spannend. das glaube ich mitlerweile auch... Nungut. Ich habe nur den Client in der Hand. Serverseitig sind das diverse fertige Geräte die alle unterschiedlich reagieren können. Ich habe jetzt zumindest dafür gesorgt das es nicht ins Nirvana läuft. Auch mit Keep alive habe ich probiert und festgestellt das von 4 Servern jeder anders reagiert. Im idealfall wird nach einer Zeit x der socket getrennt und freigegeben.
Jetzt machen wir mal nicht so ein großes Geheimnis aus den Problemen. Die bekanntesten falschen Annahmen für Netzwerkkommunikation im Allgemeinen, aus denen Probleme entstehen, findet man als: https://en.wikipedia.org/wiki/Fallacies_of_distributed_computing > 1. The network is reliable. > 2. Latency is zero. > 3. Bandwidth is infinite. > 4. The network is secure. > 5. Topology doesn't change. > 6. There is one administrator. > 7. Transport cost is zero. > 8. The network is homogeneous. Ein bisschen angestaubt, aber es ist schon mal die halbe Miete wenn man nicht diesen Denkfehlern erliegt.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.