TCP - Port hängt, wenn ACK fehlt

Gast #2496368
Lesenswert?

Hallo zusammen,

ich weiß nicht, ob das nun ein QT-spezielles Problem ist oder ein 
generelles Netzwerk Problem. In diversen QT-Forum wurde mir bislang 
nicht geholfen.

Ich sitze gerade vor folgendem Problem:
Ich habe ein Applikation unter QT, die eine Client-Server-Kommunikation 
durchführt. Dabei verbindet sich ein Client mit dem Server. Ab dann 
werden Daten in der Form gesendet, dass der Server etwas sendet und der 
Client antwortet.
Ich habe nur das Problem bei einen ungewollten Verbindungsabbruch (z.B. 
durch ziehen des Netzwerkkabels).
Mein Server ist  realisiert durch ein QTcpServer. Sobald sich der Client 
verbindet, mache ich dahin ein QTcpSocket auf (nextPendingConnection()).
Wenn nun Daten zum Client gesendet werden, aber das ACK auf dieses Paket 
nicht erfolgt, geschieht folgendes:
Mein TCP/IP-Stack scheint automatisch Keep-Alive-Messages zu senden. 
Wenn dann mehrmals keine Antwort kam, bekommt mein QTcpSocket mit, dass 
es disconnected wurde. Ein nachfolgender Versuch, die Verbindung zu 
schließen (ein FIN-Packet) schlägt dann auch fehlt.
Fatal an der ganzen Geschichte ist, dass ich den TCP/IP-Port, der hier 
nicht ordentlich geschlossen werden konnte, danach nie wieder benutzen 
kann. Erst nach einem Neustart des Computers geht es wieder.

Hat jemand einen Tipp für mich, was ich versuchen könnte?
Gast #2496374
Lesenswert?

Markus_AC schrieb:
> Fatal an der ganzen Geschichte ist, dass ich den TCP/IP-Port, der hier
> nicht ordentlich geschlossen werden konnte, danach nie wieder benutzen
> kann. Erst nach einem Neustart des Computers geht es wieder.

Es geht doch um einen PC oder? Welchens betriebssystem? Diesen Verhalten 
kann überhaupt nicht sein, weil die sockets einer anwendung zugeordnet 
sind, wenn du die Anwendung zumachst, dann werden auch alles Resourcen 
freigeben die damit verbunden sind - beleibt bestimmt nichts offen.

Was sagt denn Netstat zu diesem Port?
Moderator Persönliche Seite #2496813
Lesenswert?

Peter II schrieb:
> Diesen Verhalten
> kann überhaupt nicht sein, weil die sockets einer anwendung zugeordnet
> sind, wenn du die Anwendung zumachst, dann werden auch alles Resourcen
> freigeben die damit verbunden sind - beleibt bestimmt nichts offen.

Nein, ein nicht ordentlich geschlossener serverseitiger Port kann
für eine bestimmte Zeit vorerst nicht wieder belegt werden.  Damit
soll verhindert werden, dass beim Wiederherstellen der Verbindung
eventuell noch kursierende Pakete versehentlich einem bereits
gestarteten neuen Serverprozess zugeordnet werden, obwohl sie
eigentlich ein ICMP destination port unreachable generieren müssten,
da sie ja für die nicht ordnungsgemäß beendete Verbindung bestimmt
waren.

Der entsprechende Port sollte dann im netstat als "TIME_WAIT"
markiert sein.  Allerdings ist die Wartezeit endlich (was um die
2 Minuten vielleicht, wenn ich mich recht entsinne), und es sollte
nicht erst eines Neustarts bedürfen.

SO_REUSADDR verhindert diesen TIME_WAIT-Zustand.
Gast #2497881
Lesenswert?

Hier der Auszug aus dem Wireshark, wenn ich das Netzwerkkabel entferne.
Mein Server (192.168.214.251) sendet ein Paket mit Daten der Länge 1, 
das fehlende ACK der Clients (192.168.214.252) wird mit 5 
Keep-Alive-Messages behandelt.
Allerdings kann ich nach fast 400 Sekunden immer noch nicht den Port 
öffnen, obwohl der Default-Wert für TIME_WAIT 240 Sekunden ist. Der 
vorher geöffnete UDP Port funktioniert jedoch.
Leider habe ich bisher keine Möglichkeit gefunden, in QT die 
Socket-Option SO_REUSEADDR zu setzen.
Da es aber auch nach der TIME_WAIT Zeit nicht funktinoiert, muss noch 
etwas anderes im Argen sein...
Angehängte Dateien:
Gast #2498663
Lesenswert?

Markus_AC schrieb:
> Hier der Auszug aus dem Wireshark, wenn ich das Netzwerkkabel entferne.
> Mein Server (192.168.214.251) sendet ein Paket mit Daten der Länge 1,
> das fehlende ACK der Clients (192.168.214.252) wird mit 5
> Keep-Alive-Messages behandelt.
> Allerdings kann ich nach fast 400 Sekunden immer noch nicht den Port
> öffnen, obwohl der Default-Wert für TIME_WAIT 240 Sekunden ist. Der
> vorher geöffnete UDP Port funktioniert jedoch.
> Leider habe ich bisher keine Möglichkeit gefunden, in QT die
> Socket-Option SO_REUSEADDR zu setzen.
> Da es aber auch nach der TIME_WAIT Zeit nicht funktinoiert, muss noch
> etwas anderes im Argen sein...

Es handelt sich hier nicht um keepalives sondern um simple 
Paketwiederholungen.

Schliesst du den Socket nach dem Fehler ? Es ist kein FIN oder RST zu 
sehen. Erzeugt du eine völlig neuen Socket oder versuchst du auf dem 
altem Socket weiter zu senden ?
Welche Socket bezogenden Calls spuckt strace aus ?
Welche Sockets in welchem State werden zu verschiedenden Zeitpunkten von 
netstat -anp ausgespuckt ?

P.S.: Bitte Traces in Zukunft als *.pcap hochladen.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren