Wenn ein TCP-Client ein Paket mit einer Sequenznummer von 10000 bis 20000 an einen TCP-Server sendet. Der TCP antwortet mit einem ACK mit seq_ack 20001.
Wenn ich das TCP-Paket vom Client abfange und das Paket in 2 TCP-Segmente aufspalte, eines mit einer Sequenz von 10000 bis 15000 und das andere mit einer Sequenz von 15001 bis 20000. Und dann werden diese 2 TCP-Segmente an den TCP-Server gesendet. Angenommen, das zweite Segment ist im Pfad verloren. Der TCP-Server antwortet mit seq_ack 15001 auf eine ACK.
Da der TCP-Client nun ein integrales Paket mit der Sequenz 10000 bis 20000 sendet, aber aus Sicht des Clients eine ACK mit 15001 erhält, ist dies seltsam. Wie wird es reagieren? Theoretisch sollte der Client die Bytes von 15001 bis 20000 erneut übertragen, dh, der Client überträgt ab 15001 neue Pakete. Wie sieht es jedoch bei der Implementierung des TCP-Stacks mit der Theorie aus?
Ich denke, im TCP-Sendepuffer, wenn ein TCP-Segment gesendet wird, bleibt das Segment immer noch dort, bis die ACK. Wenn die ACK kommt, werden diese Bytes für das Segment aus dem Puffer gelöscht. Es gibt einen Zeiger im Sendepuffer, wenn ein ACK kommt, zeigt der Zeiger auf die Stelle, an der ack_seq entspricht. Die Bytes unterhalb von ack_seq werden gelöscht. Auf diese Weise muss nicht das gesamte Segment erneut übertragen werden?
quelle
Die Segmentgrößen können sich über die Lebensdauer einer Verbindung ändern. Glücklicherweise muss TCP nicht die Segmentgröße aufzeichnen, mit der einzelne Pakete zuvor gesendet wurden. Daher wird Folgendes ausgeführt:
Beide Operationen werden unabhängig von der Segmentgröße ausgeführt, in der diese Bytes ursprünglich gesendet wurden. Daher sollte die Theorie mit den meisten Implementierungen übereinstimmen.
Lassen Sie mich einige Hintergrundinformationen geben, um Folgendes zu erklären:
Verwendet TCP Bytes oder Segmente? Für die Anwendung macht TCP eine Byte-Stream-Schnittstelle verfügbar. Außerdem sind alle Headerfelder und internen Variablen in Bytes angegeben. Um Informationen zu übertragen, zerlegt TCP sie jedoch in Segmente, da das Senden von Bytes nacheinander ziemlich verschwenderisch wäre :-). Die Verwendung von Byte-Zählern überall hat den Vorteil, dass die Segmentgröße über die Lebensdauer der Verbindung nicht konstant bleiben muss:
Übrigens: SACK ist hier nicht die Antwort, da der Empfänger SACK (normalerweise) nur verwendet, wenn er eine Lücke im Bytestrom erkennt (dh wenn ein Paket verloren gegangen ist, aber ein nachfolgendes Paket eingetroffen ist).
quelle