Forum: Mikrocontroller und Digitale Elektronik lwIP TCP Timeout bei fehlerhafter Verbindung


von ztr (Gast)


Lesenswert?

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
von Ruediger A. (Firma: keine) (rac)


Lesenswert?

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.

von ztr (Gast)


Lesenswert?

hi

Es ist der Fall:  Server offline
Es kommt also keine antwort vom Server.

werde mal nach "non blocking connects" suchen

danke

von Ruediger A. (Firma: keine) (rac)


Lesenswert?

Stichwort O_NONBLOCK in lwip.

Gern geschehen!

: Bearbeitet durch User
von ztr (Gast)


Lesenswert?

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

von Jim M. (turboj)


Lesenswert?

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.

von Ruediger A. (Firma: keine) (rac)


Lesenswert?

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).

von Jim M. (turboj)


Lesenswert?

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.

von ztr (Gast)


Lesenswert?

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

von Sepp (Gast)


Lesenswert?

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

von Ruediger A. (Firma: keine) (rac)


Lesenswert?

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.

von ztr (Gast)


Lesenswert?

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.

von ztr (Gast)


Lesenswert?

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
   }

von Ruediger A. (Firma: keine) (rac)


Lesenswert?

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.

von c-hater (Gast)


Lesenswert?

ztr schrieb:

> Wie kann man also eine verlorene Verbindung erkennen?

http://tldp.org/HOWTO/TCP-Keepalive-HOWTO/overview.html

von ztr (Gast)


Lesenswert?

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

von Ruediger A. (Firma: keine) (rac)


Lesenswert?

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.

von ztr (Gast)


Lesenswert?

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.

von Jack (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.