TCP клиент-сервер SIGPIPE

Я разрабатываю и тестирую клиент-серверную программу на основе сокетов TCP (интернет-домен). В настоящее время я тестирую его на своей локальной машине и не могу понять следующее о SIGPIPE.

*. SIGPIPE появляется совершенно случайно. Может ли он быть детерминированным?

Первые тесты включали одну небольшую (25 символов) операцию отправки от клиента и соответствующий прием на сервере. Один и тот же код на той же машине работает успешно или нет (SIGPIPE) полностью вне моего контроля. Частота отказов составляет около 45% (довольно высокая). Итак, могу ли я каким-либо образом настроить машину, чтобы минимизировать это.

**. Второй раунд тестирования заключался в отправке 40000 небольших (25 символов) сообщений от клиента на сервер (1 МБ общих данных), а затем сервер отвечал общим объемом данных, которые он фактически получил. Клиент отправляет данные в замкнутом цикле, и сервер получает ОДИН вызов. Он работает только для максимум 1200 байтов общих отправленных данных, и опять же, есть эти недетерминированные SIGPIPE, примерно в 70% случаев (очень плохо).

Может ли кто-нибудь предложить некоторые улучшения в моем дизайне (вероятно, это будет на сервере). Требование состоит в том, чтобы клиент мог отправлять средний или очень большой объем данных (опять же около 25 символов в каждом сообщении) после того, как с сервером было установлено одно соединение через сокет. У меня такое ощущение, что несколько отправок против одного приема всегда будут с потерями и очень неэффективны. Должны ли мы объединять сообщения и отправлять их только в одной операции send(). Это единственный путь?


person footloose    schedule 04.03.2011    source источник


Ответы (2)


SIGPIPE отправляется, когда вы пытаетесь записать в неподключенный канал/сокет. Установка обработчика сигнала приведет к тому, что send() вместо этого вернет ошибку.

signal(SIGPIPE, SIG_IGN);

Кроме того, вы можете отключить SIGPIPE для сокета:

int n = 1;
setsockopt(thesocket, SOL_SOCKET, SO_NOSIGPIPE, &n, sizeof(n));

Кроме того, объемы данных, о которых вы говорите, не очень велики. Вероятно, где-то есть ошибка, из-за которой ваше соединение неожиданно закрывается, выдавая SIGPIPE.

person Erik    schedule 04.03.2011
comment
Обратите внимание, что SO_NOSIGPIPE не является переносимым. См. здесь: stackoverflow .com/questions/108183/ - person Craig M. Brandenburg; 18.06.2013

SIGPIPE вызывается, потому что вы пытаетесь записать в сокет, который был закрыт. Это указывает на возможную ошибку, поэтому проверьте свое приложение, чтобы понять, почему она возникает, и попытайтесь сначала исправить ее.

Попытка просто замаскировать SIGPIPE не является хорошей идеей, потому что вы на самом деле не знаете, откуда идет сигнал, и вы можете замаскировать другие источники этой ошибки. В многопоточных средах сигналы — ужасное решение.

В редких случаях, когда вы не можете этого избежать, вы можете маскировать сигнал при отправке. Если вы установите флаг MSG_NOSIGNAL для send()/sendto(), это предотвратит поднятие SIGPIPE. Если вы вызовете эту ошибку, send() вернет -1, а errno будет установлено на EPIPE. Чисто и легко. Подробнее см. man send.

person David Weber    schedule 27.01.2015