TCP Send не возвращает результат, вызывающий сбой процесса

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

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


person Danny    schedule 25.08.2009    source источник


Ответы (2)


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

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

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

person mark4o    schedule 25.08.2009

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

signal(SIGPIPE,SIG_IGN);
person nos    schedule 25.08.2009