C# - проверка состояния сокета TCP / IP со стороны клиента - PullRequest
2 голосов
/ 29 января 2020

Я бы хотел предоставить своему клиентскому классу TCP / IP функцию CheckConnection, чтобы я мог проверить, произошло ли что-то не так (мой собственный клиент отключен, сервер отключен, сервер завис, ...).
У меня есть что-то вроде этого:

bool isConnectionActive = false;
if (Client.Poll(100000, SelectMode.SelectWrite) == true)
  isConnectionActive = true;

в зависимости от того, что MSDN говорит:

SelectWrite: true, если обрабатывается соединение (EndPoint), и соединение установлено успешно; или истина, если данные могут быть отправлены; в противном случае возвращает false.

Дело в том, что, тестируя это с простым серверным приложением, я всегда получаю истину от CheckConnection, даже если сервер-слушатель был закрыт и даже если серверное приложение было закрыто; это странно, потому что я ожидаю, что в этих случаях оба соединения не обрабатываются (уже подключено минут go) и данные не могут быть отправлены.

Я уже реализовал аналогичную проверку соединения на стороне сервера, используя сочетание Poll с SelectRead и Available, и кажется, что оно работает правильно; так что теперь я должен написать что-то подобное также на стороне клиента? правильный подход SelectWrite (но я использую его неправильно)?

1 Ответ

2 голосов
/ 01 февраля 2020

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

Существуют пакеты FIN, которые следует отправлять от клиента к серверу, и наоборот, когда соединение закрыто, но нет гарантии, что они будут доставлены, или даже обработано.

Это обычно называется проблемой Half Half Open .

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

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

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

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

...