Zum Hauptinhalt springen

Ein weit verbreiteter Irrglaube ist, dass TCP die Zustellung der Daten garantiert. Was TCP tatsächlich garantiert, ist, dass es die Daten an den TCP-Stack des empfangenden Hosts liefert oder der sendenden Anwendung einen Fehler meldet. Leider gibt die Fehlermeldung keinen Aufschluss darüber, wie viele Daten tatsächlich zugestellt wurden. Es besteht auch ein erheblicher Unterschied zwischen dem empfangenden TCP-Stack und der empfangenden Anwendung.

Es gibt zwei grundlegende Fehlerszenarien. Im ersten Fall empfängt der sendende TCP-Stack keine TCP-Bestätigungen für die von ihm übertragenen Daten. In diesem Fall kann die sendende Anwendung weiterhin send aufrufen, um weitere Daten in den Sendepuffer des TCP-Stacks zu übertragen. Sobald der TCP-Stack die Übertragung beendet hat, wird beim nächsten Sende- (oder Empfangs-) Aufruf durch die sendende Anwendung der Fehler ETIMEDOUT angezeigt. Die Anwendung weiß nun, dass es ein Problem gab, hat aber keine Ahnung, wie viele Daten erfolgreich übertragen wurden. Erfolg bedeutet, dass der sendende TCP-Stack eine Bestätigung für die Daten vom empfangenden TCP-Stack erhalten hat.

Im zweiten Szenario überträgt der sendende TCP-Stack Daten und erhält statt einer Bestätigung einen Reset. Das Zurücksetzen kann darauf hinweisen, dass der empfangende TCP-Stack den Socket geschlossen hat oder ein Netzwerkgerät, vielleicht eine Firewall, eine Zeitüberschreitung verursacht hat. Das nächste Mal, wenn die sendende Anwendung send aufruft (oder empfängt), wird der Fehler ECONNRESET angezeigt. Man könnte meinen, dass die sendende Anwendung in diesem Szenario folgern könnte, dass nur die Daten des letzten Sendeaufrufs fehlgeschlagen sind, aber das wäre falsch. Es ist möglich, dass der sendende TCP-Stack die Daten mehrerer Sendeaufrufe in einem TCP-Segment gepuffert hat und dieses Segment den Reset ausgelöst hat oder dass eine Reihe von TCP-Segmenten gesendet wurde, bevor der Reset, ausgelöst durch das erste Segment in der Reihe, beim Absender ankam. Alles, was die sendende Anwendung daraus schließen kann, ist, dass nicht alle Daten erfolgreich übertragen wurden.

Es gibt ein drittes Fehlerszenario, das nichts mit dem TCP-Stack (Senden oder Empfangen) oder dem Netzwerk zu tun hat. Nehmen wir an, dass die empfangende Anwendung einen Fehler hat, der sie daran hindert, die Daten zu lesen. Der empfangende TCP-Stack wird die Daten weiterhin empfangen und TCP-Bestätigungen senden, bis der TCP-Empfangspuffer voll ist. Das können jedoch bis zu 64K Bytes an Daten sein (oder mehr, wenn TCP Window Scaling unterstützt wird). Wenn die empfangende Anwendung neu gestartet werden muss, gehen alle Daten im TCP-Empfangspuffer verloren. Der empfangende TCP-Stack sollte (muss aber nicht) einen Reset an den sendenden TCP-Stack senden, wenn die empfangende Anwendung beendet wird. Er sendet ein Reset, wenn er das nächste Mal ein Segment für die nun geschlossene Verbindung empfängt. Aus der Sicht der sendenden Anwendung ist dies ähnlich wie das zweite Szenario. Es weist jedoch darauf hin, dass selbst wenn der empfangende TCP-Stack die Daten bestätigt, der Absender im Falle eines Fehlers nicht davon ausgehen kann, dass die empfangende Anwendung die Daten gelesen hat.

Die Idee, die man aus diesen Fehlerszenarien mitnehmen kann, ist, dass eine Zeitüberschreitung bei der Übertragung oder ein Reset-Fehler ohne eine Bestätigung der Anwendungsschicht darauf hinweist, dass einige, möglicherweise alle übertragenen Daten von der empfangenden Anwendung nicht gelesen wurden. Aus diesem Grund empfehle ich, dass alle Anwendungen Acknowledgments der Anwendungsschicht einschließen, darauf vorbereitet sind, eine Verbindung wiederherzustellen und unbestätigte Daten erneut zu übertragen, und dass sie in der Lage sind, mit doppelten Daten umzugehen, da die Acknowledgements verloren gegangen sein könnten.

© 2024 Stratus Technologies.