как определить подключение клиента tcp к серверу в С++

У меня есть клиент/сервер tcp, и я хочу обнаружить потерю соединения на стороне клиента; поскольку мой клиент имеет несколько интерфейсов, и одновременно я подключался к серверу с одним из них, я хочу знать, как обнаружить потерю соединения на стороне клиента, чтобы я мог подключить свой TCP-клиент с другим интерфейсом к серверу, и если все они Я храню свои данные в текстовых файлах. Я погуглил, и я уже видел, как сохранить жизнь, но это не то, что я хочу.

если это важно, мой проект находится в Linux, а код - в C++.


person Lrrr    schedule 22.04.2013    source источник


Ответы (3)


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

person mah    schedule 22.04.2013
comment
если потеря интерфейса, это подключение к Интернету, это закрывает сокет? (все мои интерфейсы 3g) - person Lrrr; 22.04.2013
comment
Да. Удаленной машине может потребоваться некоторое время, чтобы это заметить (но вы хотите, чтобы это время было принято, чтобы предотвратить ложное закрытие сокета из-за сетевых проблем между двумя машинами). - person mah; 22.04.2013
comment
Почему вы когда-либо открывали соединение и не имели поток чтения? Я не имею в виду в отдельной теме. Я имею в виду, какой смысл иметь клиентское соединение, если вы не читаете из сокета? - person Serge Ivanoff; 22.04.2013
comment
@SergeIvanoff не каждому приложению требуется двунаправленная связь, и также разумно иметь протокол приложения, который, например, читает один раз в начале, а затем входит в цикл (длительная задержка для обработки / и т. д.), запись - не нужно читать тем временем (за исключением случаев, когда вы хотите обнаружить удаленное отключение, чтобы прервать работу по обработке). - person mah; 22.04.2013
comment
Верно, спасибо. Но чтение может сидеть неопределенно долго и не возвращать ошибочный ответ, если сокет не завершен, если вы не кодируете тайм-аут. - person Serge Ivanoff; 22.04.2013
comment
Вам не нужен тайм-аут при чтении обязательно. Как только ваша локальная система узнает, что сокет больше не действителен, она разблокирует чтение, что приведет к его возврату (с ошибкой). Локальная система не узнает сразу, если удаленное устройство выйдет из строя (или будет отключено от сети и т. д.), поэтому тайм-аут все еще может быть полезен для повышения скорости отклика, в зависимости от потребностей приложения. - person mah; 22.04.2013
comment
@mah Я ​​читаю из сокета, но, похоже, для этого нет тайм-аута; это занимает слишком много времени, и функция чтения по-прежнему ничего не возвращает! - person Lrrr; 23.04.2013

Соединения TCP предназначены для исправления ошибок и не критичны по времени. Это исправление ошибок включает тайм-ауты сети.

Чтение и запись не завершатся ошибкой до тех пор, пока сокет не будет фактически закрыт, что может произойти не очень долго.

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

Вот для чего нужны сообщения Keep Alive.

person Serge Ivanoff    schedule 22.04.2013
comment
Мой клиент вообще не получит никаких сообщений! из-за нашего дизайна только клиент будет отправлять сообщения на сервер! если мой клиент получит сообщения, мне будет очень легко обнаружить соединение клиента и сервера! - person Lrrr; 23.04.2013
comment
В таком случае никак. Если есть задержка в сети, TCP буферизует сообщения в попытке восстановиться после повторного установления соединения. Я уверен, что есть какая-то причина, по которой вы получите сообщение о заполнении буфера, если запишете слишком много данных, но это зависит от размеров базового сетевого буфера. Дизайн вашего сервера должен измениться, чтобы отправлять уведомления об активности (или сообщения о состоянии, если хотите). - person Serge Ivanoff; 24.04.2013
comment
Я решил проблему без поддержки активности и других ответов от сервера. - person Lrrr; 24.04.2013

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

person Lrrr    schedule 24.04.2013
comment
Классная идея. Как вы избегаете состояния гонки, если слишком рано проверяете этот ioctl? Также SIOCOUTQ, по-видимому, специфичен для Linux означает, что это не решение для разработчика Windows. - person Serge Ivanoff; 26.04.2013
comment
@SergeIvanoff Я знаю, что это не поддерживается в Windows, но, как я уже упоминал в вопросе, я пишу код в Linux и ищу решение своей проблемы; Я не задавал этот вопрос, чтобы решить чужие проблемы! если я проверю ioctl слишком рано, я подожду, пока он ответит, если я получу ошибку, я не просто закрыл свой сокет, если ioctl не ответил, но я буду ждать почти 1 минуту, и если в это время мои данные все еще остаются в буфере, я закрою сокет. - person Lrrr; 27.04.2013