LINUX.ORG.RU

Проверка TCP-соединения, C

 , , ,


0

2

Привет, ЛОР.

Что-то не могу найти инфу по проверке TCP-соединения клиентом.

Смысл такой:
Клиент подключается к серверу и ждет от него инфу (ждет бесконечно и ничего без команды сервера не делает, главное для него - не пропустить сообщение от сервера)
В какой-то момент связь с сервером теряется/сервер зависает/сервер рвет соединение/меняются сетевые настройки или происходит еще что-то плохое.
Пока что в основной петле Epoll я проверяю приходящие данные на клиентском сокете:

    while(1)
    {
        numOfNewEvents = epoll_wait(epollFD, epollEventArray, MAX_EPOLL_EVENTS, EPOLL_RUN_TIMEOUT);

        for(i = 0; i < numOfNewEvents; i++) 
        {
            eventSource = epollEventArray[i].data.fd;

            ...

            // Что-то пришло на сокет(всегда ли, случись что, оно будет приходить?)
            if(eventSource == clientSocket) 
            {
                numOfReadBytes = recv(eventSource, dataBuffer, MAX_TCP_BUF_SIZE, 0);
                if(numOfReadBytes > 0)
                {
                    // Приехал пакет. Что-то делаем с ним
                }
                else
                {
                    // Разрыв соединения. Пытаемся до посинения переподключиться, сообщаем юзеру и т.д.
                }
            }

            ...

        }      
    }

Ну и собственно вопрос: для всех ли случаев подойдет такая обработка?
Некоторые из возможных вариантов развития событий(тут может быть куча вариантов):

  • Сеть пропала, после восстановилась
  • Сеть пропала, сервер вырубился, сеть восстановилась
  • Сервер вырубился, потом включился
  • Сеть пропала, сервер перезагрузился, сеть восстановилась
  • Сеть пропала, сервер закрыл соединение, сеть восстановилась
  • Админ сменил ориентацию и поменял нам IP


Последнее исправление: vgovseychuk (всего исправлений: 1)

Пропадание сети не обнаружишь до попытки непосредственной записи в сокет и/или чтения из сокета.
Либо включай SO_KEEPALIVE, либо предусматривай какие-то тайм-ауты на прикладном уровне.

Гуглить: tcp dead connection detection

mkam
()
Последнее исправление: mkam (всего исправлений: 1)
Ответ на: комментарий от mkam

Да в общем-то с пропаданием сети ничего не нужно делать. Главное - поймать момент, когда она восстановилась. Вот и спрашиваю, поймает ли момент восстановления мой обработчик.

vgovseychuk
() автор топика
Ответ на: комментарий от vgovseychuk

Не поймает. FIN/RST пакет не пришёл. Клиент не знает, что соединение сдохло. Если не знает, что оно сдохло, то не будет переподключаться.

mkam
()
Ответ на: комментарий от mkam

либо предусматривай какие-то тайм-ауты на прикладном уровне.

Ок, можно предусмотреть. Тогда вытекает следующий вопрос:
Есть ли какие-то служебные функции для этого? Что послать серверу, чтобы он не принял это за данные или за закрытие соединения?

vgovseychuk
() автор топика
Ответ на: комментарий от vgovseychuk

Из служебных SO_KEEPALIVE. Но прежде чем это включать почитай внимательно о механизме.

Сервер не тобою написан? В чём сложность обработки сервером набора байтов от клиента, который будут расцениваться как keep alive-пакет?

mkam
()
Ответ на: комментарий от vgovseychuk

Почитаю тогда про KEEPALIVE. Плюсы, минусы, подводные камни. Единственное, все пишут про серверную сторону, но может и про клиентскую что найду.

vgovseychuk
() автор топика
Ответ на: комментарий от vgovseychuk

Вот в этом и проблема=) Поэтому и спрашиваю про служебные.

В параллельном потоке пинговать сервер с желаемой частотой? Кстати, а какое максимальное время допускается до обнаружения обрыва соединения?

gag ★★★★★
()
Ответ на: комментарий от gag

какое максимальное время допускается до обнаружения обрыва соединения?

Думаю, пользователем будет определяться.

В параллельном потоке пинговать сервер с желаемой частотой?

Я знаю, что сервер пускает TCP и только для авторизованного соединения. Про ICMP не знаю, да и лишнее это, я думаю.

И кстати, про SO_KEEPALIVE: какие могут быть проблемы с этим?

vgovseychuk
() автор топика

Я бы еще добавил в epoll флаг EPOLLRDHUP.


EPOLLRDHUP (since Linux 2.6.17)
Stream socket peer closed connection, or shut down writing half of connection. (This flag is especially useful for writing simple code to detect peer shutdown when using Edge Triggered monitoring.)

joy4eg ★★★★★
()
Ответ на: комментарий от vgovseychuk

Думаю, пользователем будет определяться.

Я не о точном значении, а о порядке: часы, минуты, секунды?

Я знаю, что сервер пускает TCP и только для авторизованного соединения.

Так ведь для авторизации он это соединения должен сначала принять и разобраться. Вот тебе и пинг.

Про ICMP не знаю, да и лишнее это

Ну, это как передавать файлы по почте SMTP, когда для этих целей был придуман FTP.

И кстати, про SO_KEEPALIVE: какие могут быть проблемы с этим?

Мутное дело. Самому интересно. Учитывая, что стандартное значение 2 часа - оно, возможно, для какой-то другой цели было изначально.

gag ★★★★★
()
Ответ на: комментарий от gag

И кстати, про SO_KEEPALIVE: какие могут быть проблемы с этим?

Похоже, и с безопасностью тоже (из мана ssh_config):

It is important to note that the use of server alive messages is very different from TCPKeepAlive (below). The server alive messages are sent through the encrypted channel and therefore will not be spoofable. The TCP keepalive option enabled by TCPKeepAlive is spoofable. The server alive mechanism is valuable when the client or server depend on knowing when a connection has become inactive.

Так что если серверное ПО претендует на защищённость, значит, оно должно предусматривать пустые NOP-пакеты.

gag ★★★★★
()

У SO_KEEPALIVE существенная проблема: кроме опции на сокете необходимо ещё вообще включить этот keepalive в системе, иначе keepalive-пакеты отправляться не будут. Ну и значение таймаута между keepalive-пакетами - тоже системное.

Если вас это устраивает, то пользуйтесь, оно работает. Если нет, да и вообще, попробуйте найти ping в вашем протоколе взаимодействия клиента с сервером, ну или хотя бы данные, которые сервер просто игнорировал бы, не отправляя ничего в ответ.

Sorcerer ★★★★★
()
Ответ на: комментарий от gag

Так ведь для авторизации он это соединения должен сначала принять и разобраться. Вот тебе и пинг.

fail2ban

Stil ★★★★★
()
Ответ на: комментарий от Stil

Я fail2ban использую только для бана после нескольких неуспешных логинов по ssh. А он ещё и авторизовывать соединения умеет, а после авторизации пробрасывать именно это соединение собственно серверу? Тупо по IP, конечно. Но не более, ведь? Или имеется ввиду port knocking? Но это не авторизация, а обфускация.

gag ★★★★★
()
Ответ на: комментарий от gag

Не, я к тому, что если использовать рабочий сервак в качестве пинговалки, то можно остаться без рабочего справка.

Stil ★★★★★
()
Ответ на: комментарий от Stil

ну, fail2ban ещё не самое страшное. страшное - это обузяторы разных контор, которые ревностно бдят, а не шлёшь ли ты подозрительно много пакетов. и потом докажи, что не верблюд. мы работали с DNS, у нас иногда гонялись тесты на устойчивость к ддосам разным. провайдеры это плохо воспринимают. так что тренироваться лучше во внутрисетке.

Iron_Bug ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.