Der TCP-Socket empfängt keine Daten mehr, bis er geschlossen wird

8

Ich habe ein wirklich seltsames Problem, das mich verrückt macht.

Ich habe einen Ruby-Server und einen Flash-Client (ActionScript 3). Es ist ein Multiplayer-Spiel.

Das Problem ist, dass alles perfekt funktioniert und plötzlich hört ein zufälliger Spieler auf, Daten zu empfangen. Wenn der Server die Verbindung wegen Inaktivität ca. 20-60 Sekunden später schließt, erhält der Client alle gepufferten Daten.

Der Client verwendet XMLsocket zum Abrufen von Daten, daher ist die Art, wie der Client Daten empfängt, nicht das Problem.

%Vor%

Der Server löscht die Daten nach jedem Schreibvorgang. Es handelt sich also nicht um ein Spülproblem:

%Vor%

DATAEOF ist ein Null-Zeichen, daher analysiert der Client die Zeichenfolge.

Wenn der Server einen neuen Socket akzeptiert, setzt er sync auf true, auf autoflush und TCP_NODELAY auf true:

%Vor%

Das ist meine Forschung:

Info: Ich habe Netstat-Daten jede Sekunde in eine Datei geschrieben.

  • Wenn der Client keine Daten mehr empfängt, zeigt netstat an, dass der Socket-Status weiterhin ESTABLISHED ist.
  • Einige Sekunden später wächst send-queue entsprechend den gesendeten Daten.
  • tcpflow zeigt, dass Pakete zweimal gesendet werden.
  • Wenn der Server den Socket schließt, ändert sich der Socketstatus wie erwartet in FIN_WAIT1 . Dann zeigt tcpflow, dass alle gepufferten Daten an den Client gesendet werden, der Client jedoch keine Daten empfängt. Einige Sekunden später verschwindet die Verbindung von netstat und tcpflow zeigt an, dass die gleichen Daten erneut gesendet werden, aber dieses Mal empfängt der Client die Daten und beginnt Daten an den Server zu senden und der Server empfängt sie. Aber es ist zu spät ... Server hat die Verbindung geschlossen.

Ich glaube nicht, dass es ein OS / Netzwerk-Problem ist, weil ich von einem VPS in Spanien zu Amazon EC2 in Irland gewechselt habe und das Problem immer noch besteht.

Ich glaube auch nicht, dass es sich um ein Client-Netzwerkproblem handelt, da dies Dutzende Male pro Tag vorkommt und die durchschnittliche Anzahl der Online-Benutzer etwa 45-55 ist, mit etwa 400 Unique Usern pro Tag, also ist das Verhältnis extrem hoch hoch.

BEARBEITEN: Ich habe mehr geforscht. Ich habe den Server in C ++ geändert.

Wenn ein Client keine Daten mehr sendet, erhält der Server nach einiger Zeit den Fehler "Verbindung durch Peer zurückgesetzt". In diesem Moment zeigt mir tcpdump, dass der Client ein RST-Paket gesendet hat, weil der Client die Verbindung geschlossen hat und der Server versucht hat zu lesen, aber ... warum der Client die Verbindung geschlossen hat? Ich denke, die Antwort ist, dass der Client nicht derjenige ist, der die Verbindung schließt, ist der Kernel. Hier sind einige Informationen: Ссылка

Basically, as I understand it, Linux kernels 2.6.17+ increased the maximum size of the TCP window/buffer, and this started to cause other gear to wig out, if it couldn’t handle sufficiently large TCP windows. The gear would reset the connection, and we see this as a “Connection reset by peer” message.

Ich bin den Schritten gefolgt und jetzt scheint es, dass der Server Verbindungen nur schließt, wenn der Klient seine Verbindung zum Internet verliert.

Ich füge das als Antwort hinzu, damit die Leute ein bisschen mehr darüber wissen.

    
Jorge Fuentes González 05.09.2012, 09:27
quelle

1 Antwort

2

Ich denke, die Antwort ist, dass der Kernel derjenige ist, der die Verbindung schließt. Hier sind einige Informationen: Ссылка

Basically, as I understand it, Linux kernels 2.6.17+ increased the maximum size of the TCP window/buffer, and this started to cause other gear to wig out, if it couldn’t handle sufficiently large TCP windows. The gear would reset the connection, and we see this as a “Connection reset by peer” message.

Ich bin den Schritten gefolgt und jetzt scheint es, dass der Server Verbindungen nur schließt, wenn der Klient seine Verbindung zum Internet verliert.

    
Jorge Fuentes González 10.10.2012, 14:48
quelle