„Die Anwendung läuft seit Jahren einwandfrei. Letzte Woche wurde das Netzwerk aufgerüstet und wir sind von 100 Mbit/s auf Gigabit umgestiegen. Jetzt ist die zweite Hälfte der Daten in einigen Nachrichten unlesbar. Die Netzwerktechniker schwören, dass es nicht am Netzwerk liegt – aber das ist das Einzige, was sich geändert hat.“
Die gute Nachricht ist, dass die teure Netzwerkaufrüstung die Anwendung nicht beschädigt hat.
Die schlechte Nachricht ist, dass die Anwendung fehlerhaft ist und schon immer fehlerhaft war. Was *viele* Entwickler von TCP-Anwendungen nicht wissen, ist, dass TCP ein Byte-Stream ist und keine Nachrichten überträgt. Die Tatsache, dass eine Anwendung zwei 1000-Byte-Nachrichten sendet, bedeutet nicht, dass der sendende TCP-Stack zwei 1000-Byte-TCP-Segmente sendet. Die Anwendungsnachrichten können entweder basierend auf der vom Empfänger angegebenen maximalen Segmentgröße oder aufgrund einer Konfigurationsbeschränkung auf der Senderseite in kleinere Teile segmentiert werden. Auch bei erneuten Übertragungen können Anwendungsnachrichten kombiniert und fragmentiert werden. Selbst wenn der sendende TCP-Stack tatsächlich zwei 1000-Byte-TCP-Segmente sendet, gibt es keine Garantie dafür, dass der empfangende TCP-Stack der empfangenden Anwendung zwei 1000-Byte-Nachrichten übermittelt. Wenn der Puffer der Anwendung beispielsweise nur 500 Byte groß ist, gibt der TCP-Stack auch nur diese Menge zurück. Ist der Puffer hingegen 1500 Byte groß und sind beide 1000-Byte-Segmente angekommen, gibt der TCP-Stack beim ersten Aufruf 1500 Byte und beim zweiten Aufruf 500 Byte zurück. Es ist Aufgabe der Anwendung, den Byte-Stream zu übernehmen und ihn korrekt in Nachrichten zu parsen.
Was hat das mit der Aufrüstung des Netzwerks zu tun? Nun, der OpenVOS-Server und der Linux-Client befanden sich in unterschiedlichen Subnetzen, sodass das OpenVOS-System eine maximale Segmentgröße von 536 Byte ankündigte. Die vom Client gesendeten Anwendungsnachrichten waren 1000 Byte groß, sodass die Nachrichten in zwei Teile segmentiert wurden. Vor dem Upgrade schienen beide Segmente beim OpenVOS-Server anzukommen, bevor die Anwendung ihren Empfang meldete, sodass alle 1000 Byte mit einem Aufruf der Empfangsfunktion gelesen wurden. Nach dem Upgrade änderte sich das Segmenttiming, sodass manchmal nur das erste Segment verfügbar war, wenn die Anwendung ihren Empfang meldete. Die letzten 464 (1000 – 536) Bytes des Anwendungsbuffers wurden vom TCP-Stack nicht gefüllt und enthielten den vor dem Senden des Empfangs vorhandenen Datenmüll.
In diesem Fall gab es eine einfache Schnelllösung: Erhöhen Sie den von OpenVOS angegebenen MSS-Wert auf 1460 (siehe Eine einfache Möglichkeit zur Verbesserung des TCP-Durchsatzes über Subnetze hinweg). Das ist jedoch nur eine Notlösung. Die eigentliche Lösung besteht darin, den Code so umzuschreiben, dass der TCP-Byte-Stream korrekt in Anwendungsnachrichten zurückübersetzt wird, anstatt einfach davon auszugehen, dass 1 Empfangsfunktion 1 Nachricht zurückgibt.
