2011-01-03 17 views
54

Wiem, że przerwany błąd rury jest generowany, gdy gniazdo po stronie peer jest zamknięte.Co powoduje błąd zepsutej rury?

Ale w moim teście zauważyłem, że natychmiastowe wywołanie "wyślij" po tej stronie, gdy strona równorzędna jest zamknięta, nie zawsze prowadzi do zerwania błędu rury.

Np

Po zamknięciu gniazda na boku rówieśniczej (Próbowałem czystego zamknięcia wywołując bliskie, a także nieprawidłowe zamknięcie zabijając peer), gdy próbuję wysłać 40 bajtów, to ja nie rozumiem zepsuta rura, ale jeśli spróbuję wysłać 40000 bajtów, natychmiast poda zepsuty błąd rury.

Co dokładnie powoduje uszkodzenie rury i czy można przewidzieć jej zachowanie?

Odpowiedz

39

Zamknięcie sieci może zająć trochę czasu - całkowity czas wynosi nominalnie około 2 minut (tak, minuty!) Po zamknięciu, zanim wszystkie pakiety przeznaczone do portu zostaną uznane za martwe. W pewnym momencie zostaje wykryty warunek błędu. Po niewielkim wpisie znajdujesz się wewnątrz jednostki MTU systemu, więc wiadomość jest w kolejce do wysłania. Z dużym napisem jesteś większy niż MTU i system szybciej dostrzega problem. Jeśli zignorujesz sygnał SIGPIPE, funkcje zwrócą błąd EPIPE na uszkodzonej rurze - w pewnym momencie, gdy wykryte zostanie zerwanie połączenia.

+4

@varevarao: Nie sądzę, że kolejkowanie transmisji i wysyłanie w określonych odstępach czasu jest obejściem problemu. Transmisje w kolejce, dopóki nie zostanie wysłana więcej niż MTU, może być obejściem, jeśli aplikacja może żyć z opóźnieniami. –

3

Może 40 bajtów pasuje do bufora potoku, a 40000 bajtów nie?

Edit:

Proces wysyłania zostaje wysłany do SIGPIPE podczas próby zapisu do zamkniętej rurze. Nie wiem dokładnie, kiedy wysyłany jest sygnał, ani jaki wpływ ma na niego bufor rur. Możesz być w stanie odzyskać przez pułapkę sygnału z wezwaniem sigaction.

6

Aktualny stan gniazda jest określany przez aktywność "keep-alive". W twoim przypadku jest to możliwe, że podczas wywołania send, aktywność keep-alive mówi, że gniazdo jest aktywne, a więc wywołanie send zapisze wymagane dane (40 bajtów) do bufora i zwróci bez podania jakiegokolwiek błędu .

Gdy wysyłasz większą porcję, połączenie przychodzące przechodzi do stanu blokowania.

Strona man wyślij potwierdza to również:

Gdy wiadomość nie pasuje do bufora wysyłania gniazda, send() normalnie bloki, chyba że gniazdo zostało umieszczone w non-blocking I/Tryb O. W trybie non-blocking byłoby powrócić EAGAIN w tym przypadku

Tak, blokując do swobodnego dostępnego bufora, jeśli zostanie powiadomiony rozmówca (przez mechanizm podtrzymania), że drugi koniec nie bardziej obecny, tym wysłanie połączenia nie powiedzie się.

Przewidywanie dokładnego scenariusza jest trudne z tymi informacjami, ale uważam, że to powinien być powód problemu.

+1

Aktualny stan gniazda jest obserwowany przez aktywność ACK. Funkcja Keepalive jest tylko jedną z mniejszych aktywności ACK źródła i domyślnie jest wyłączona. – EJP

Powiązane problemy