LINUX.ORG.RU

Работа с сокетами


0

2

Пытаюсь понять следующую ситуацию: есть сервер, есть клиент, взаимодействуют через сокеты(TCP), все работает. Жмем reset на сервере.

1)Теперь кто должен отвечать за сброс соединения на клиенте при условии что клиент в состояниии простоя ждет когда ему придут данные с сервера и сам ниче не посылает

2)Сервер загрузился. Должно ли соединение клиента и сервера восстановиться автоматически? На практике не восстанавливается, требуется перезапуск клиента.

★★★

1. Используй неблокирующие сокеты и будет тебе счастье.
2. Зависит от архитектуры приложения. Если ты достаточно грамотный программист - реализуй, чтоб восстанавливалось. Пользователи скажут тебе спасибо.

Ну и много может зависеть от библиотеки, которая тебе доступ к сокетам предоставляет.

trex6 ★★★★★ ()

1) ОС клиента
2) не должен. с какой стати? все данные из ОЗУ (в их число входит и информация о соединениях) канули в небытие. автовосстановление соединения может быть реализовано только непосредственно в серверном и клиентском приложениях.

xydo ★★ ()

>Жмем reset на сервере.

Если «reset» это кнопка на системном блоке, то:

1. В протоколе взаимодействия должна быть реализована проверка работоспособности связи, либо установлены спец опции на сокет (забыл какие). TCP по умолчанию не гарантирует разрыв соединения при падении сервера.

2. Однозначно не должно.

pathfinder ★★★ ()
Ответ на: комментарий от pathfinder

>>Должно ли соединение клиента и сервера восстановиться автоматически?

2. Однозначно не должно.

Хотя, что понимается под словом автоматическое соединение. У клиента будет разрыв соединения, после которого он может заново инициировать соединение, а может и не инициировать.

pathfinder ★★★ ()

Требуется ручное применение fsck, я полагаю.

Mobyshvein ()
Ответ на: комментарий от pathfinder

Ну о том и думаю. Просто решил спросить друг чего не знаю про сокеты и понапишу щас лишнего кода.

Использую glibc.

TheMixa ★★★ ()

Как я понимаю в случе использования сокетов из glibc придется писать код который в заданном интервале будет проверять хождение пакета от клиента к серверу и назад? Бибилотека такого функционала непосредственно не предоставяет?

TheMixa ★★★ ()
Ответ на: комментарий от TheMixa

>Бибилотека такого функционала непосредственно не предоставяет?

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

Проблема в том, что такое удобно реализовать с использованием схемы select()/poll()/epoll()+«конечный автомат». Но у такого похода высокий порог вхождения. С нуля за две минуты не освоишь.

Если использовать обычное блокирующее чтение/запись+multithreading, то делать такое ИМХО не очень удобно.

pathfinder ★★★ ()

1) стек TCP/IP
2) После того как сервер загрузился, и клиент будет к нему делать конекты то сервер пошлёт клиенту флаг RST.

Boy_from_Jungle ★★★★ ()
Ответ на: комментарий от Boy_from_Jungle

>>при условии что клиент в состояниии простоя ждет когда ему придут данные с сервера и сам ниче не посылает

1) стек TCP/IP

Если не сделать SO_KEEPALIVE для сокета, то стек TCP/IP тебе ничего не гарантирует. Высока вероятность что он разорвет соединение, но это не гарантировано. Плохой ситуацией является как раз состояние простоя, о котором говорил ТС.

Если сделать SO_KEEPALIVE, то могут быть проблемы с большими таймаутами (около 2-х часов) на разрыв соединения. Эту проблему можно решить с помощью дополнительных непортабельных опций TCP_KEEPCNT, TCP_KEEPIDLE, TCP_KEEPINTVL. Но ИМХО этого лучше не делать. Это не портабельно, ты будешь получать ответы от стека TCP/IP, а не от самого приложения. Согласен что со всем этим можно спорить, но реализация собственной проверки на уровне приложения избавляет от необходимости использовать специфические опции, все можно сделать стандартным способом. Если созданный протокол начнут использовать на других платформах и в этом протоколе отсутствуют примитивы проверки линии, то возникнут трудности.

pathfinder ★★★ ()
Ответ на: комментарий от Boy_from_Jungle

>2) После того как сервер загрузился, и клиент будет к нему делать конекты то сервер пошлёт клиенту флаг RST.

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

pathfinder ★★★ ()
Ответ на: комментарий от Boy_from_Jungle

>в TCP/IP всё описываеться. Так что при желании можно всё найти.

Если я в чем то не прав, то дай пожалуйста развернутый ответ. А то ты как-то уклончиво ответил.

pathfinder ★★★ ()
Ответ на: комментарий от pathfinder

>Похоже ты забываешь про MSL и TIME_WAIT

MSL - maximum segment timelife.

TIME_WAIT - одно из состояний конечного автомата TCP. В это состояние он переходит когда закрывается сокет. Система тупо ждет интервал времени равный 2*MSL, после чего выходит из этого состояния. Потом она уже может освободить этот сокет для повторного использования. Соответственно пока сокет находится в состоянии TIME_WAIT он никем использован быть не может, хоть и уже закрыт приложением. Только для этого и нужно это ожидание, типа мы не используем сокет для новых соединений, пока не рассосутся все пакеты от старого соединения, гуляющие по сети. Это все нужно для того, чтобы в новом соединении не схватить фантомные пакеты от старого соединения.

Я вот так все это понимаю. Если я где-то не прав, поправь меня. Сейчас мне не понятно, какое отношение этот TIME_WAIT имеет к тому, что я говорил.

pathfinder ★★★ ()
Ответ на: комментарий от TheMixa

у tcp есть keepalive. Ты можешь его подтюнить в ведре. Так же периодичность keepalive, вроде, можно через setsockopt тюнить(а не глобально для всех прог), но это я точно не помню, поищи в инете

true_admin ★★★★★ ()
Ответ на: комментарий от true_admin

>у tcp есть keepalive. Ты можешь его подтюнить в ведре. Так же периодичность keepalive, вроде, можно через setsockopt тюнить(а не глобально для всех прог), но это я точно не помню, поищи в инете

Об этом уже говорилось. Опции SO_KEEPALIVE,TCP_KEEPCNT,TCP_KEEPIDLE,TCP_KEEPINTVL. Таже сказано о недостатках такого подхода.

pathfinder ★★★ ()
Ответ на: комментарий от pathfinder

Сознаюсь, лень было трэд читать, я думал до этого никто не додумается.

true_admin ★★★★★ ()
Ответ на: комментарий от true_admin

в хорошие годы за такое руки вырывали! мож ты ведро подтюнишь, чтобы и коннекшин клиент востанавливал автоматом?

anonymous ()
Ответ на: комментарий от pathfinder

>Опции SO_KEEPALIVE,TCP_KEEPCNT,TCP_KEEPIDLE,TCP_KEEPINTVL

Решил пока попробовать так, всеравно только linux<->linux. Пока не делал но возник вопрос где должно отловиться в таком случае потеря соединения если соединене сбросилось?

1)на select?

2)на FD_ISSET?

3)на read?

Я понимаю так:

select()

if(FD_ISSET())

if(read()==0)

//closed connections. Try reopen

else

//fine

Получается что гдето до FD_ISSET надо еще както отлавливать что соединение рухнуло? Или FD_ISSET для закрытого соединения по keepalive вернет чтото отличное от нуля?

TheMixa ★★★ ()
Ответ на: комментарий от TheMixa

Насколько я понимаю read() возвращает ноль, если соединение было нормально закрыто. Т.е. на уровне TCP произошла нормальная процедура закрытия соединения между двумя компьютерами.

Если произошел сбой в сети, то вместо нуля возвратится -1 с соотвествующим кодом ошибки. Коды нужных ошибок на память не помню.

Тебе надо определять потерю соединения не только через read()==0 но и через анализ ошибок при read()==(-1).

pathfinder ★★★ ()
Ответ на: комментарий от pathfinder

Это я понимаю. Главное что если оборвется по keepalive то FD_ISSET() не «промолчит»?

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

TheMixa ★★★ ()
Ответ на: комментарий от anonymous

Чувак, не кипятись, выростишь - поймёшь. Да, у меня в ведре так и подтюнено чтобы не висели мёртвые соединения. Раз в 20 сек keepalive. Скрипты которые работают с сетью стали надёжнее отваливаться в случае проблем.

true_admin ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.