Каков наилучший способ реализовать heartbeat на C ++ для проверки подключения к сокету?

StackOverflow https://stackoverflow.com/questions/495922

  •  20-08-2019
  •  | 
  •  

Вопрос

Привет, банда.Я только что написал клиент и сервер на C ++, используя sys / socket.Мне нужно справиться с ситуацией, когда клиент все еще активен, но сервер не работает.Один из предлагаемых способов сделать это - использовать сердцебиение для периодического подтверждения подключения.И если такового нет, пытаться переподключаться каждые X секунд в течение Y периода времени, а затем переходить на тайм-аут.

Является ли это "сердцебиение" лучшим способом проверить наличие подключения?

Сокет, который я использую, может содержать информацию о нем, есть ли способ проверить наличие соединения, не вмешиваясь в буфер?

Это было полезно?

Решение

Если вы используете TCP-сокеты по IP-сети, вы можете использовать функцию keepalive протокола TCP, которая будет периодически проверять сокет, чтобы убедиться, что другой конец все еще там.(Это также имеет то преимущество, что запись пересылки для вашего сокета остается действительной на любых маршрутизаторах NAT между вашим клиентом и вашим сервером.)

Вот такой Обзор TCP keepalive в котором описываются некоторые из причин, по которым вы, возможно, захотите использовать TCP keepalive; это РУКОВОДСТВО для конкретного Linux описывает, как настроить ваш сокет для использования TCP keepalive во время выполнения.

Похоже, вы можете включить TCP keepalive в сокетах Windows, установив SIO_KEEPALIVE_VALS используя WSAIoctl() функция.

Если вы используете UDP-сокеты по IP, вам нужно будет встроить свой собственный heartbeat в свой протокол.

Другие советы

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

Самое простое решение состоит в том, чтобы клиент периодически отправлял данные, а сервер закрывал соединение, если он не получал никаких данных от клиента в течение определенного периода времени.Это идеально работает для протоколов запросов / ответов, где клиент отправляет запросы, а сервер отправляет ответы.

Например, вы можете использовать следующую схему:

  1. Сервер отвечает на каждый запрос.Если сервер не получает запрос в течение двух минут, он закрывает соединение.

  2. Клиент отправляет запросы и сохраняет соединение открытым после каждого из них.

  3. Если клиент не отправлял запрос в течение одной минуты, он отправляет запрос "вы там".Сервер отвечает "да, это так".Это сбрасывает двухминутный таймер сервера и подтверждает клиенту, что соединение все еще доступно.

Возможно, было бы проще просто попросить клиента закрыть соединение, если ему не нужно было отправлять запрос в течение последней минуты.Поскольку все операции инициируются клиентом, он всегда может просто открыть новое соединение, если ему необходимо выполнить новую операцию.Это сводит все только к этому:

  1. Сервер закрывает соединение, если он не получил запрос в течение двух минут.

  2. Клиент закрывает соединение, если ему не понадобилось отправлять запрос в течение одной минуты.

Однако это не гарантирует клиенту, что сервер присутствует и готов принять запрос в любое время.Если вам нужна эта возможность, вам придется внедрить в свой протокол запрос / ответ "вы там", "да, я здесь".

Если другая сторона ушла (т.е.процесс завершился, компьютер вышел из строя и т.д.), попытка получить данные из сокета должна привести к ошибке.Однако, если другая сторона просто подвешена, розетка останется открытой.В этом случае полезно иметь сердцебиение.Убедитесь, что любой протокол, который вы используете (поверх TCP), поддерживает какой-либо запрос "ничего не делать" или пакет - каждая сторона может использовать это, чтобы отслеживать, когда они в последний раз получали что-то от другой стороны, и затем может закрыть соединение, если между пакетами проходит слишком много времени.

Обратите внимание, что это предполагает, что вы используете TCP / IP.Если вы используете UDP, то это совсем другое дело, поскольку он не имеет подключения.

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

Если вы находитесь между чтением и записью, ожидая пользовательского ввода, закройте сокет.Разработайте свой клиентско-серверный протокол (предполагая, что вы делаете это вручную и не используете какие-либо стандартные протоколы, такие как http и / или SOAP), чтобы справиться с этим.

Сокеты выдадут ошибку, если соединение будет разорвано;напишите свою программу таким образом, чтобы вы не теряли никакой информации в случае такой ошибки во время записи в сокет и чтобы вы не получали никакой информации в случае ошибки во время чтения из сокета.Транзакционность и атомарность должны быть встроены в ваш клиентско-серверный протокол (опять же, при условии, что вы разрабатываете его самостоятельно).

может быть, это поможет вам, КАК Сохранить TCP В актуальном СОСТОЯНИИ или это ТАК_СОКЕТ

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top