Название: KeepAlive у TCP Отправлено: Orfus от Декабрь 04, 2010, 15:44 Доброго времени суток читающим сие.
Вступление: Я реализую сервер и клиент общающиеся посредством протокола TCP. На данный момент, клиент подключается к серверу, сервер его видит. Клиент разъединяется (происходит выключение клиентской программы) сервер это тоже видит. Проблема же возникла в некорректном отключении, т.е. если кто-то выдернул сетевой кабель. Сигналов об этом "событии" не приходит. Возник вопрос, как же всё таки об этом событии узнать. Есть классическое решение посылать пакеты "я живой" и если за определённый интервал времени не пришло ни одного пакета ответа ( или пакета "я живой") считать противоположную сторону отключённой. Однако, решение вроде бы есть в самом qt http://doc.qt.nokia.com/4.7/qabstractsocket.html#setSocketOption (http://doc.qt.nokia.com/4.7/qabstractsocket.html#setSocketOption) Цитировать void QAbstractSocket::setSocketOption ( QAbstractSocket::SocketOption option, const QVariant & value ) Устанавливает заданную опцию option равным значению, описываемым значением value. Эта функция была введена в Qt 4.6. --- enum QAbstractSocket::SocketOption Данное перечисление представляет опции, которые могут быть установлены у сокета. Если требуется, они могут установить после получения сигнала connected() от сокета или после получения нового сокета от QTcpServer. Константа Значение Описание QAbstractSocket::LowDelayOption 0 Пытается оптимизировать сокет для уменьшения времени ожидания. Для TcpSocket будет установлена опция TCP_NODELAY и отключён алгоритм Nagle. Установите равной 1 для включения. QAbstractSocket::KeepAliveOption 1 Установите равным 1 для включения опции сокета SO_KEEPALIVE This enum was introduced or modified in Qt 4.6. Но что-то либо я делаю не так, либо необходимо поднастроить. Собственно кусок кода: Код: //Конструктор QTcpServer У клиента всё ещё веселее: Код: //инициализация нити ответственной за сеть Собственно вопросы в том как донастроить у сервера, почему клиент выдаёт -255 и не проще ли самому руками слать пакеты "я живой" ? Qt 4.7.0 пишу под WinXP. Тестировал на Win7 (на нём и было -255), на Win Vista, WinXP. Приложение разрабатывается только под локальную сеть. Заранее благодарен за ответы) Название: Re: KeepAlive у TCP Отправлено: BRE от Декабрь 04, 2010, 16:04 Информация по SO_KEEPALIVE из книги Стивенса
Цитировать Параметр сокета SO_KEEPALIVE Двухчасовой интервал это значение по умолчанию, его можно изменить.Когда параметр SO_KEEPALIVE установлен для сокета TCP и в течение 2 часов не происходит обмена данными по сокету в любом направлении, TCP автоматически посылает собеседнику проверочное сообщение (keepalive probe). Это сообщение - сегмент TCP, на который собеседник должен ответить. Далее события могут развиваться по одному из трех сценариев 1) Собеседник отвечает, присылая ожидаемый сегмент ACK. Приложение не получает уведомления(поскольку всё в порядке). TCP снова отправляет проверочное сообщение ещё через 2 часа отсутствия активности в этом соединении 2) Собеседник отвечает, присылая сегмент RST, который сообщает локальному TCP, что узел собседника вышел из строя и перегрузился. Ошибка сокета, требующая обработки, устанавливается равной ECONNRESET, и сокет закрывается 3) На проверочное сообщение не приходит ответ от собеседника. Код TCP, происходящий от Беркли, отправляет 8 дополнительных проверочных сообщений с интервалом в 75 секунд, пытаясь выявить ошибку. TCP прекратит попытки, если ответа не последует в течение 11 минут и 15 секунд после отправки первого сообщения. Если на все проверочные TCP не приходит ответа, то ошибка сокета, требующая обработки, устанавливается в ETIMEDOUT, и сокет закрывается. Если же сокет получает ошибку ICMP (Internet Control Message Protocol - протокол управляющих сообщений Интернета) в ответ на одно из проверочных сообщений, то возвращается одна из соответствующих ошибок (табл A.3 и A.4), но сокет также закрывается. Типичная ошибка ICMP в этом сценарии - Host unreachable (Узел недоступен) - указывает на то, что узел собеседника не вышел из строя, а только является недоступным. При этом ошибка, ожидающая обработки, устанавливается в EHOSTUNREACH Наверное для своего протокола проще сделать свой ping/pong. Название: Re: KeepAlive у TCP Отправлено: Orfus от Декабрь 04, 2010, 18:54 А не подскажите ли как сменить интервал?
Название: Re: KeepAlive у TCP Отправлено: BRE от Декабрь 04, 2010, 18:58 А не подскажите ли как сменить интервал? Почитай про:int setsockopt(int socket, int level, int option_name, const void *option_value, socklen_t option_len); Название: Re: KeepAlive у TCP Отправлено: Orfus от Декабрь 04, 2010, 19:17 Премного благодарен)
Название: Re: KeepAlive у TCP Отправлено: Orfus от Декабрь 09, 2010, 00:16 Решение пришлось выкапывать из бОльших глубин ;D
Код: .... Дословно я часть не понял (возможно косяк с dwBytes), но эта штука работает. А моё первое правило если работает, не трожь ;D кстати говоря, после [2] {2} я на всякий случай для себя решил вызвать: Код: ... |