TCP-Fenster werden für die Flusssteuerung zwischen den Peers einer Verbindung verwendet. Mit jedem ACK-Paket sendet ein Host ein "Fenstergröße" -Feld. In diesem Feld wird angegeben, wie viele Datenbytes der Host empfangen kann, bevor er voll ist. Der Sender soll nicht mehr als diese Datenmenge senden.
Das Fenster wird möglicherweise voll, wenn der Client die Daten nicht schnell genug empfängt. Mit anderen Worten, die TCP-Puffer können sich füllen, während die Anwendung ausgeschaltet ist und etwas anderes als das Lesen von ihrem Socket ausführt. Wenn dies geschieht, würde der Client ein ACK-Paket mit dem gesetzten "Fenster voll" -Bit senden. An diesem Punkt soll der Server aufhören, Daten zu senden. Alle Pakete, die an ein Gerät mit einem vollen Fenster gesendet werden, werden nicht bestätigt. (Dies führt dazu, dass sich ein Sender mit schlechtem Verhalten erneut sendet. Ein Sender mit gutem Verhalten puffert die ausgehenden Daten. Wenn der Puffer auf der sendenden Seite ebenfalls voll ist, wird die sendende Anwendung blockiert, wenn sie versucht, mehr Daten in den Socket zu schreiben !)
Dies ist ein TCP-Stall. Es kann aus vielen Gründen passieren, aber letztlich bedeutet es nur, dass der Sender schneller sendet, als der Empfänger liest.
Sobald die App auf der Empfangsseite wieder zum Lesen aus dem Socket kommt, werden einige der gepufferten Daten gelöscht, was etwas Speicherplatz freigibt.Der Empfänger sendet dann ein "Fensteraktualisierungs" -Paket, um dem Absender mitzuteilen, wie viele Daten er übertragen kann. Der Sender beginnt mit der Übertragung seiner gepufferten Daten und der Datenverkehr sollte normal verlaufen.
Natürlich können Sie wiederholte Ställe erhalten, wenn der Empfänger durchgängig langsam ist.
Ich habe dies so formuliert, als ob Sender und Empfänger unterschiedlich sind, aber in Wirklichkeit tauschen beide Peers Fensteraktualisierungen mit jedem ACK-Paket aus, und beide Seiten können ihr Fenster ausfüllen.
Die allgemeine Nachricht ist, dass Sie Fensteraktualisierungspakete nicht direkt senden müssen. Es wäre eigentlich eine schlechte Idee, einen aufzuspielen.
In Bezug auf die Ausnahme, die Sie sehen ... wird es wahrscheinlich nicht verursacht oder durch das Fenster-Update-Paket verhindert werden. Wenn der Client jedoch nicht schnell genug liest, verlieren Sie möglicherweise Daten. Auf Ihrem Server sollten Sie den Rückgabewert Ihrer Socket.write() -Aufrufe überprüfen. Es könnte weniger als die Anzahl der Bytes sein, die Sie schreiben möchten. Dies passiert, wenn der Sendepuffer des Senders voll wird, was während eines TCP-Stalls passieren kann. Sie könnten Bytes verlieren.
Zum Beispiel, wenn Sie versuchen, 8192 Bytes bei jedem Aufruf schreiben zu schreiben, aber eine der Anrufe zurück 5691, dann müssen Sie die verbleibenden 2501 Bytes auf den nächsten Anruf senden. Andernfalls wird der Client den Rest dieses 8K-Blocks nicht sehen und Ihre Datei wird auf der Clientseite kürzer sein als auf der Serverseite.
Mein Bug-Fu sagt mir, dass dieser letzte Absatz sehr wahrscheinlich das Problem genagelt haben wird. – caf
Große Erklärung, danke! Genau das, was ich brauchte. Ich glaube, ich fand die Ursache der Ausnahme - der Client wurde erwartet, dass die Daten in einer anderen, etwas längeren Form als das, was ich sendete. – phpscriptcoder
+1 für die detaillierte Erklärung! – Izza