Что происходит с сокетами, когда я отключаю сетевой кабель? - PullRequest
7 голосов
/ 13 января 2009

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

Вот краткий набросок вещи:

alt text

Теперь, когда я отсоединяю сетевой кабель от ПК2 (красное соединение «Con B»), внутреннее соединение перестает говорить (синее соединение «Con A»). Я посылаю материал из «Приложения 1» в сокет, который никогда не попадает в «Приложение 2».

Я создал механизм, который обнаруживает это и отключает, а затем снова подключает, и после этого я могу отключить кабель, сколько захочу, и «Con A» просто продолжает работать. Это только в первый раз.

Я подтвердил наличие связи через «Con A» перед отключением «Con B».
Я подключаюсь и подключаюсь точно так же, это тот же код, поэтому нет никакой разницы.

Что происходит?

Дополнительная информация по ответам: ПК 1 и ПК 2 имеют общие адреса вплоть до последнего байта.
У меня есть внутренний механизм поддержки активности, я отправляю сообщение и жду ответа каждые 10 секунд.
Когда я убиваю приложение 3, этого не происходит, только при отключении кабеля.

Ответы [ 3 ]

5 голосов
/ 13 января 2009

На некоторых платформах (окнах) вытягивание сетевого кабеля говорит сетевому стеку активировать недействительные соединения с открытыми сокетами, связанные с интерфейсом.

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

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

5 голосов
/ 13 января 2009

Какой адрес вы используете для «Кон А»? Если вы используете адрес, который привязан к внешнему сетевому адаптеру, даже если вы разговариваете с той же машиной, то то, что вы описываете, может произойти.

Что вы можете сделать, это использовать адрес localhost (127.0.0.1) для «Con A», который должен быть полностью независим от того, что происходит во внешней сети.

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

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

Мой сервер Linux, с другой стороны, справляется с этим довольно изящно. После продолжительной (30-40 секунд) отмены кабельного соединения на днях SSH-соединение с моего ноутбука на сервер все еще было доступно и быстро реагировало.

Пока кабель не отключен дольше, чем время ожидания TCP, стек должен иметь возможность буферизовать пакеты и повторно передавать их как можно скорее. TCP предназначен для этого. Если вы не используете TCP, пакеты выпадают из дыры Ethernet и испаряются в атмосферу.

@ einstein: Если вы используете select () или производные, то никогда не выбирайте с NULL таймаутом. Всегда имейте разумное время ожидания и проверьте состояние сокета, если оно истекает.

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