TCP Send не возвращает причину сбоя процесса - PullRequest
8 голосов
/ 25 августа 2009

Если tcp-сервер и клиент подключены, я бы хотел определить, когда клиент больше не подключен. Я думал, что могу просто сделать это, пытаясь отправить сообщение клиенту, и как только send () возвращается с -1, я могу затем разрушить сокет. Эта реализация работает в Windows, но в ту минуту, когда я пытаюсь сделать это в Linux с сокетами BSD, вызов send () в приложении на стороне сервера приводит к сбою приложения на моем сервере, если клиент больше не подключен. Он даже не возвращает -1 ... просто завершает программу.

Пожалуйста, объясните, почему это происходит. Заранее спасибо!

Ответы [ 2 ]

15 голосов
/ 26 августа 2009

Это вызвано сигналом SIGPIPE.См. send(2):

Функция send () не будет работать, если:
[EPIPE] Сокет отключен для записи или установлен в режиме подключенияи больше не подключен.В последнем случае, если сокет имеет тип SOCK_STREAM или SOCK_SEQPACKET и флаг MSG_NOSIGNAL не установлен, сигнал SIGPIPE генерируется в вызывающий поток.

Этого можно избежать, используя MSG_NOSIGNAL флаг при вызове send() или игнорирование сигнала SIGPIPE с помощью signal(SIGPIPE, SIG_IGN) в начале вашей программы.Тогда функция send() вернет -1 и установит errno в EPIPE в этой ситуации.

2 голосов
/ 26 августа 2009

Вы должны игнорировать сигнал SIGPIPE. Если происходит ошибка записи в сокет, ваш процесс использует команду get SIGPIPE, и поведение этого сигнала по умолчанию - уничтожение вашего процесса. Написание сетевого кода на * nix, который вы обычно хотите:

signal(SIGPIPE,SIG_IGN);
...