2009-08-25 10 views
8

Jeśli serwer TCP i klient są ze sobą połączone, chciałbym ustalić, kiedy klient nie jest już połączony. Myślałem, że mogę to zrobić po prostu próbując wysłać wiadomość do klienta i gdy send() wróci z -1, mogę wtedy odłączyć gniazdo. Ta implementacja działa w systemie Windows, ale w chwili, gdy próbuję to zrobić w systemie Linux z gniazdami BSD, wywołanie funkcji send() w aplikacji po stronie serwera powoduje awarię mojej aplikacji serwera, jeśli klient nie jest już połączony. Nawet nie zwraca -1 ... tylko kończy program.Wysyłanie protokołu TCP nie zwraca przyczyny powodującej awarię:

Proszę wyjaśnić, dlaczego tak się dzieje. Z góry dziękuję!

Odpowiedz

13

Jest to spowodowane sygnałem SIGPIPE. Zobacz send(2):

send() funkcja powinna zawieść jeżeli:
[EPIPE] Gniazdo jest zamknięty na piśmie, czy gniazdo jest połączenie w trybie i nie jest już podłączony. W tym ostatnim przypadku i jeśli gniazdo ma typ SOCK_STREAM lub SOCK_SEQPACKET i flaga MSG_NOSIGNAL nie jest ustawiona, sygnał SIGPIPE jest generowany do wątku wywołującego.

Można tego uniknąć stosując flagę MSG_NOSIGNAL na wezwanie send() lub ignorując sygnał SIGPIPE z signal(SIGPIPE, SIG_IGN) na początku programu. Wtedy funkcja send() powróci -1 i ustawi errno na EPIPE w tej sytuacji.

2

Należy zignorować sygnał SIGPIPE. Jeśli błąd zapisu wystąpi w gnieździe, twój proces z otrzymaniem SIGPIPE i domyślnym zachowaniem tego sygnału to zabicie twojego procesu. Zapisywanie kodu sieciowego na * nix zwykle potrzebujesz:

signal(SIGPIPE,SIG_IGN); 
Powiązane problemy