Okna TCP służą do sterowania przepływem między urządzeniami równorzędnymi w połączeniu. Przy każdym pakiecie ACK host wysyła pole "rozmiar okna". W tym polu podano liczbę bajtów danych, które host może otrzymać, zanim będzie pełny. Nadawca nie powinien wysyłać więcej niż ta ilość danych.
Okno może się zapełnić, jeśli klient nie otrzymuje wystarczająco szybko danych. Innymi słowy, bufory TCP mogą się zapełniać, gdy aplikacja jest wyłączona, robiąc coś innego niż odczyt z gniazda. Gdy tak się stanie, klient wyśle pakiet ACK z ustawionym bitem "pełnego okna". W tym momencie serwer powinien przestać wysyłać dane. Wszelkie pakiety wysłane do komputera z pełnym oknem będą uznawane za , a nie. (To spowoduje, że źle zachowany nadawca będzie retransmitował. Dobrze zachowany nadawca będzie po prostu buforował wychodzące dane .Jeśli bufor po stronie wysyłającej również się zapełni, to aplikacja wysyłająca zablokuje, gdy spróbuje zapisać więcej danych do gniazda !)
To jest stoisko TCP. Może się tak zdarzyć z wielu powodów, ale ostatecznie oznacza to, że nadawca przesyła szybciej niż czyta odbiornik.
Gdy aplikacja na końcu odbierającym wróci do odczytu z gniazda, spowoduje to odessanie niektórych buforowanych danych, co zwalnia trochę miejsca.Odbiorca wyśle pakiet "aktualizacji okna", aby poinformować nadawcę, ile danych może przesłać. Nadawca rozpoczyna przesyłanie swoich zbuforowanych danych, a ruch powinien odbywać się normalnie.
Oczywiście można uzyskać powtarzające się przeciągnięcia, jeśli odbiornik jest konsekwentnie wolny.
Sformułowałem to tak, jakby nadawca i odbiorca byli inni, ale w rzeczywistości, obydwa węzły wymieniają aktualizacje okien z każdym pakietem ACK, a każda ze stron może zapełnić swoje okno.
Ogólna wiadomość jest taka, że nie trzeba bezpośrednio wysyłać pakietów aktualizacji okien. Byłoby złym pomysłem, aby je podrobić.
Jeśli chodzi o wyjątek, który widzisz ... prawdopodobnie pakiet SVP nie będzie powodował ani mu zapobiegnie. Jeśli jednak klient nie czyta wystarczająco szybko, możesz utracić dane. Na swoim serwerze powinieneś sprawdzić wartość zwracaną przez połączenia Socket.write(). Może być mniejsza niż liczba bajtów, które próbujesz napisać. Dzieje się tak, gdy bufor nadawczy zostanie zapełniony, co może się zdarzyć podczas przeciągnięcia TCP. Możliwe, że tracisz bajty.
Na przykład, jeśli próbujesz napisać 8192 bajtów przy każdym wywołaniu zapisu, ale jedna z wywołań zwraca 5691, musisz wysłać pozostałe 2501 bajtów przy następnym połączeniu. W przeciwnym razie klient nie zobaczy pozostałej części tego bloku 8K, a twój plik będzie krótszy po stronie klienta niż po stronie serwera.
Mój bug-fu mówi mi, że ten ostatni akapit prawdopodobnie przytył problem. – caf
Świetne wyjaśnienie, dzięki! Dokładnie to, czego potrzebowałem. Myślę, że znalazłem przyczynę wyjątku - klient oczekiwał danych w innej, nieco dłuższej formie niż to, co wysyłałem. – phpscriptcoder
+1, aby uzyskać szczegółowe wyjaśnienie! – Izza