feat(core): SYN+ACK and FIN go once, as in Java, measured with Java FILIUS
TcpRun loses exactly one frame (loseFirst: the card's output buffer drops it; the sender's packet log still shows it, as with setDrop) in three new stories: lostSynAck, lostFin, lostLastFin. Measured: Java never repeats a SYN+ACK or a FIN. The server gives a handshake up after one timeout (3 RTT) and closes with a FIN from SYN_RCVD (its boundary check sometimes lets it wait twice; it means once). After its FIN a socket waits at most five times, each wait ended by a segment or the timeout; then it is gone. The core does the same (TCP_CLOSING_WAITS, with TIME_WAIT in the loop) and shows CLOSED where Java leaves the state standing (a named Java bug). One departure: a repeated SYN in SYN_RCVD gets the SYN+ACK once more and the wait starts anew; Java closes there, but its client never repeats the SYN. lostSynAck is compared up to the second SYN (JAVA_UNTIL); the rest is an engine test. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -203,6 +203,17 @@ und Mitschnitt teilen `DhcpRun` und `TcpRun` in `ScenarioNetwork`.
|
||||
* `lostData`: verbunden, dann gehen alle Frames verloren
|
||||
(`Verbindung.setDrop`, wie der Paketverlust des Kerns), während der Client
|
||||
sendet; der Verlust endet, wenn `senden` scheitert.
|
||||
* `lostSynAck`: das erste SYN+ACK des Servers geht verloren.
|
||||
* `lostFin`: verbunden, der Client schließt; sein FIN geht verloren.
|
||||
* `lostLastFin`: verbunden, der Client schließt; das FIN des Servers geht
|
||||
verloren.
|
||||
|
||||
Einen einzelnen Frame verliert `loseFirst`: Per Reflection ersetzt es den
|
||||
Ausgangspuffer der Karte (`Port.ausgangsPuffer`) durch einen, der den ersten
|
||||
passenden Frame verwirft, statt ihn einzureihen. Das Kabel wartet am alten
|
||||
Puffer und wird dort einmal geweckt. Der Lauscher des Absenders sieht den
|
||||
Frame wie bei `setDrop` (er schreibt nach dem Einreihen); anders als dort
|
||||
belegt der Frame das Kabel nicht.
|
||||
|
||||
Gemessen (30.09.2026, 90 %, RTT 2750 ms), was Swift anders macht:
|
||||
|
||||
@@ -220,6 +231,14 @@ Gemessen (30.09.2026, 90 %, RTT 2750 ms), was Swift anders macht:
|
||||
`connectClientMode` `closeSocket`, und die Schleife über drei Versuche
|
||||
endet (`verbinden` scheitert nach 3 RTT). Der Server-Socket wiederholt sein
|
||||
SYN+ACK nie.
|
||||
* Nach einem verlorenen SYN+ACK gibt der Server nach 3 RTT auf und schickt aus
|
||||
`SYN_RCVD` ein FIN (`close`). In zwei von drei Läufen wartete er 6 RTT: Der
|
||||
Vergleich `vergangen > defaultTimeout()` liegt genau auf der Grenze.
|
||||
* Ein FIN geht einmal hinaus, nie wieder. Danach wartet `close` höchstens
|
||||
fünfmal 3 RTT; jedes ankommende Segment beendet eine Wartezeit. Dann ist
|
||||
der Socket weg, sein Zustand bleibt aber stehen (`FIN_WAIT_1`,
|
||||
`FIN_WAIT_2`, `LAST_ACK`). Die Gegenseite eines verlorenen FIN bleibt
|
||||
`ESTABLISHED`.
|
||||
* Startnummern aus einem Zähler über alle TCP-Sockets (1000000, 2000000, …),
|
||||
wie im Kern; der freie Port ist zufällig.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user