Crazy Hamster
> то на сервер придет соответствующий TCP пакет
Хм... это какой-то стандартный пакет? Как его отловить? Обычным recv(...)?
Sergio
Ну вот например.
http://msdn.microsoft.com/en-us/library/ms740121%28v=vs.85%29.aspx
Return Value
If no error occurs, recv returns the number of bytes received and the buffer pointed to by the buf parameter will contain this data received. If the connection has been gracefully closed, the return value is zero.
У вызова close(socket) нужно обязательно обрабатывать возвращаемое значение на ошибки.
Так как при закрытии может вернуться уведомление о неготовности соккете закрыться. Нужно подождать и вызвать закрытие по новой.
В этих случаях ответная сторона не узнает о закрытии. И соккет отвалится аварийно. Сам много времени убил на такой косяк.
При обработке проблемы пропадают.
Sergio
> Хм... это какой-то стандартный пакет? Как его отловить? Обычным recv(...)?
Системное уведомление о закрыти не поступает в поток на чтение и обрабатывать его не нужно. Скрыто в протоколе уровнем ниже.
Соккеты блокируемые?
Sergio
в tcp/ip гарантируется, что пакеты данные будут доставлены без искажений и в надлежащем порядке.
либо система явно выкинет ошибку.
функции recv и send возвращают кол-во переданных байт, либо код ошибки, либо код, что соединение корректно закрыто с того конца.
Поэтому если что-то будет не то со связью, то данные функции обязательно выкидывают соответствующую ошибку.
Пингование описанное тобой применяется для случая, когда запросы к серверу редки, а контролировать реальное положение дел надо чаще, если для бизнес-логики отправителя нет необходимости знать об отключенных соединениях раньше чем средний период отправки пакета, то пинг может быть и не нужен.
Некоторые применяют пинг для попытки отлова "молчунов", которые просто грузят систему. Например, делая "неявный" ддос, когда система не отказывает, но работает тяжело, что создает плохое впечатление у игроков, либо выжирает лимиты трафика. Но здесь момент следующий, любой мало мальски грамотный кулхацкер способен симулировать различные секретные системы пингования, если, конечно, вы не разработчики скайпа.
В Вашем случае с брокен пайп, это, ЕМНИП, ошибка связанная с тем, что отправитель пытается отправить, а получатель получать не хочет или не может.
Это, возможно, если сокет закрылся не полностью, а только один свой поток, например, поток на чтение, а Вы ему отправить что-то хотите.
Либо, получатель закрыл сокет полностью.
Либо отвалился.
Я так понимаю сервер под юникс?
Тут надо конкретно смотреть код работы с сокетами с обоих сторон и, конкретно, настройки при создании.
А также политику работы с сокетами с точки зрения потоков.
Sergio
> мы получаем ошибку сокета "Broken Pipe"
песать в отсоединённый сокет не есть гуд :)
ловите ноль байт в recv() и закрывайте сокет, чтобы неповадно было
Сокеты неблокируемые.
Результат close() не проверяется, контроля за нулем recv() тоже нету.
Судя по всему одним сервером тут не обойдешься...
Sergio
> Желательно конечно обойтись только изменением сервера
>Судя по всему одним сервером тут не обойдешься...
% ))
если линух
close() проверять на EAGAIN
recv() проверять на ноль
накрайняк можно просто обработать SIGPIPE
>Сокеты неблокируемые
честно я уже не помню зачем есть такая возможность (ща даже гляну ради интереса)
достаточно блокирующих с демультиплексором select/poll/epoll
как ты клиент не переделывай, но не всегда сервер будет знать все о клиентах. кто-то закрыл клиент допустим через диспетчер задач и всё... сервер в неведении "куда он делся", поэтому нужно его кикнуть с сервера по тайм ауту.
Sergio
> Сокеты неблокируемые.
это дает 95% гарантию того, что закрытие с первого раза не получится. И такуюже гарантию на то, что целиком данные отправленные в send не уйдут.
Я из-за этого терял часть данных в потоке, пока не понял в чем дело. Привык работать с блокируемыми соккетами. Там все гарантированно. В неблокируемых - нет.
Sergio
> Судя по всему одним сервером тут не обойдешься...
Если соединение рвет клиент, то на сервере можно только красиво обработать эту ситуацию,чтобы ошибки не валились. Лечить всё равно надо клиента.
Megabyte-Ceercop
> это дает 95% гарантию того, что закрытие с первого раза не получится. И такуюже гарантию на то, что целиком данные отправленные в send не уйдут.
> Я из-за этого терял часть данных в потоке, пока не понял в чем дело. Привык работать с блокируемыми сокетами. Там все гарантированно. В неблокируемых - нет.
В блокируемых сокетах гарантировано только завершение операции по выходу из функции и не более того. Данные посланные на сокет уйдут по-любому.
А разве с блокируемыми сокетами не будет подтормаживания или зависания во время отправки? Надо будет потестить, так как данные передаются небольшими порциями, но часто.
И видимо все-таки придется лечить клиент, потому что текущая версия скомпилированна с интервалом пинга 1 с. и таймаутом 10 с.
Megabyte-Ceercop
> это дает 95% гарантию того, что закрытие с первого раза не получится. И такуюже
> гарантию на то, что целиком данные отправленные в send не уйдут.
нет, просто задача(отправка,закрытие, прием) будет выполняться не синхронно, а асинхронно.
Sergio
> А разве с блокируемыми сокетами не будет подтормаживания или зависания во время
> отправки?
поток, вызывавший send,recv при блокируемых сокетах, блокируется до полного исполнения задачи или ошибки.
Sergio
> А разве с блокируемыми сокетами не будет подтормаживания или зависания во время отправки?
Поэтому, обычно, работу с блокируемыми сокетами в отдельный thread засовывают. Чтобы интерфейс не тормозил.
Megabyte-Ceercop
> это дает 95% гарантию того, что закрытие с первого раза не получится
вообще-то закрытие регулируется опцией SO_LINGER а не флагом O_NONBLOCK
просто в линухе есть специфичный прикол (кста мож в текущем ядре уже и нету)
что там даже без этой опции, если в буфере отправки чего-то было на момент закрытия,
то в errno возвращается EWOULDBLOCK ( = EAGAIN )
Sergio
> так как данные передаются небольшими порциями, но часто.
убей писавшего апстенку : )
ТСР это грузовой протокол, заточенный под передачу большого количества данных
writev() слегка спасает в случае когда MSG = HDR + BODY
Sh.Tac.
> ТСР это грузовой протокол, заточенный под передачу большого количества данных
хм, не встречал такой характеристики. Можно пояснить?
Тема в архиве.