Как узнать состояние TCP соединения с SO_KEEPALIVE

367 views
Skip to first unread message

Антон Агеев

unread,
May 5, 2014, 2:44:58 PM5/5/14
to gola...@googlegroups.com
Есть TCP соединение (net.TCPConn) с включенным режимом SO_KEEPALIVE. Никакие данные не передаются и не принимаются. Предположим, удаленная сторона была поглощена черной дырой. По идее, после нескольких фейлов в доставке keepalive probe пакетов, ОС должна пометить соединение как закрытое.

Вопрос: как нам в Go узнать об этом?

На ум приходит дергать периодически getsockopt(..., SO_ERROR, ...), но боюсь это может нарушить работу поллера в рантайме Go.

Void Nugget

unread,
May 6, 2014, 1:23:47 PM5/6/14
to gola...@googlegroups.com
Читаем, prob'ы пишутся раз в два часа, так что толку от этого мало
В форточках лечится вот так, в *nix'ах задаётся параметрами ядра.
Конкретно в линуксе так.

К сожалению параметры keep-alive глобальны для всего TCP стэка ядра.
Обычно на уровне протокола проще слать "пустые" NOP пакеты если требуется "локальный keepalive".

Понеділок, 5 травня 2014 р. 21:44:58 UTC+3 користувач Антон Агеев написав:

Anton Ageev

unread,
May 6, 2014, 2:18:16 PM5/6/14
to gola...@googlegroups.com
Интервал между probe-пакетами можно задавать и для каждого сокета отдельно (по крайней мере в linux).
А вот узнать о том, что сокет был закрыт ОС узнать никак в приложении нельзя. Только при попытке прочитать или записать что-то в сокет, соответствующая функция вернёт ошибку. Причем это все безотносительно Go, в сишечки точно такая же проблема.

P.S. В венде данная проблема как-то решается через свои API, но вот венда меня как раз мало интересует.



--
Вы получили это сообщение, поскольку подписаны на группу "Golang Russian".
Чтобы отменить подписку на эту группу и больше не получать от нее сообщения, отправьте письмо на электронный адрес golang-ru+...@googlegroups.com.
Чтобы настроить другие параметры, перейдите по ссылке https://groups.google.com/d/optout.



--
WBR, Anton

Void Nugget

unread,
May 6, 2014, 5:28:15 PM5/6/14
to gola...@googlegroups.com
Да, забыл о флагах TCP_KEEPINTVL, TCP_KEEPIDLE и TCP_KEEPCNT в setsockopt.
Явных инструментов проверить "зомби" сокет в природе не существует в виду самой природы TCP, пока не пройдёт FIN-ACK с обоих сторон - сокет считается закрытым.
Обычно пишут NOP'ы и проверяют ошибки, так как с обратной стороны при записи должно приходить подтверждение - если его нет, по таймауту возвращается ошибка.

Вівторок, 6 травня 2014 р. 21:18:16 UTC+3 користувач Антон Агеев написав:

Void Nugget

unread,
May 6, 2014, 5:31:08 PM5/6/14
to gola...@googlegroups.com
p.s. *пока не пройдёт FIN-ACK с обоих сторон - сокет считается открытым. Пишите в джаббер конфу gol...@jabber.ru там чуть быстрее ответ получите.

Середа, 7 травня 2014 р. 00:28:15 UTC+3 користувач Void Nugget написав:

Aln Kapa

unread,
May 7, 2014, 1:20:22 AM5/7/14
to gola...@googlegroups.com
Добрый день.

Вопрос в тему. К примеру ответная часть живет за NAT, будут гарантированно в этом случае работать keepalive или лучше решать вопрос жизни клиента посылкой noop пакетов?


7 мая 2014 г., 1:31 пользователь Void Nugget <void....@gmail.com> написал:

Dmitry Vyukov

unread,
May 7, 2014, 2:40:48 AM5/7/14
to gola...@googlegroups.com
2014-05-07 9:20 GMT+04:00 Aln Kapa <aln...@gmail.com>:
> Добрый день.
>
> Вопрос в тему. К примеру ответная часть живет за NAT, будут гарантированно в
> этом случае работать keepalive или лучше решать вопрос жизни клиента
> посылкой noop пакетов?


Я сталкивался с ошибкой в одном из популярных антивирусов на винде, в
результате которого ядро продолжало считать tcp соединение живым после
смерти процесса, и радостно продолжало отвечать на keepalive по этому
соединению. В результате чего на линукс сервере была куча мертвых
соединений от завершившихся клиентов.
Application-level keepalive все же надежнее.
Reply all
Reply to author
Forward
0 new messages