Каков наилучший способ реализовать биение в C ++ для проверки подключения к сокету? - PullRequest
8 голосов
/ 30 января 2009

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

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

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

Ответы [ 5 ]

12 голосов
/ 30 января 2009

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

Вот обзор TCP keepalive , в котором описаны некоторые причины, по которым вы можете захотеть использовать TCP keepalive; В этом специфическом для Linux HOWTO описывается, как настроить сокет для использования протокола поддержки активности TCP во время выполнения.

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

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

3 голосов
/ 24 сентября 2012

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

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

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

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

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

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

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

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

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

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

2 голосов
/ 30 января 2009

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

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

1 голос
/ 30 января 2009

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

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

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

0 голосов
/ 30 января 2009

возможно, это вам поможет, TCP Keepalive HOWTO или это SO_SOCKET

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...