LINUX.ORG.RU

закрытие сокета


0

2

привет всем!

такой вот вопрос, помогите разобраться.

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

С моей чайниковской точки зрения — посылать keepalive периодически.

GotF ★★★★★ ()

таймайт

Я могу ошибаться, но при ошибке соединения запрос чтения вернет ошибку (-1) или 0. Хотя это зависит от ЯП.

На это форуме есть один парень с ником telepathy, он большой спец в сокетах и прочем, но кажется куда-то уехал. Он должен точно знать.

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

тестирую через глобальную сеть.

сервер - пока классический пример на сокетах на С.

kabanchik ()

хм с чем это связано?

роутер или удалённая сторона прибил соединение

как мне сделать

keepalive. Можно на уровне протокола периодически посылать данные, можно на уровне сокета выставить keepalive interval(через setcokopt, если не путаю, подробности в гугле).

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

может быть

а почему же тогда сервер никак на это не реагирует...клиентский процесс на стороне сервера продолжает ждать жить

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

В смысле не отваливается? Это реальность с которой приходится жить :(. Я правильно понимаю что как минимум одна из тачек у тебя за натом? Серваки с реальными ипами так не тупят потому что между ними нет таких вот маршрутизаторов которые молча дропают пакеты.

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

роутер или удалённая сторона прибил соединение

Простите за мою безграмотность, если что, но разве роутер может прибить соединение, он ведь работает на уровне IP, а не на уровне TCP.

pathfinder ★★★★ ()

Может дурацкий вопрос, но его следует задать. Вы ведь там проверяете возврат функции write(), т. е. нет ошибок, и самое главное число реально записанных байт в сокет соответствует тому, что вы собирались записать?

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

по идее nat может. Не будет же он держать соединение в таблице вечно

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

да как бы дочерний процес на стороне сервера блокируется на ожидании данных, т.е. на read() и функция ничего не возвращает...после долгого таймайта со стороны клиента

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

если что, но разве роутер может прибить соединение, он ведь работает на уровне IP, а не на уровне TCP.

nat и фаерволы(не все, только stateful) работают на уровне tcp. Более того, они даже udp отслеживают, иначе бы за натом udp не работал.

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

число реально записанных байт в сокет соответствует тому, что вы собирались записать?

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

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

нет, тачки в разных углах города

ну, в общем, снифер всё покажет. Но можно с этим не париться, явно проблема с таймаутами и keepalive спасёт.

Я полагаю что если с одного сервера на другой зайти по ssh и долго не трогать консольку то она тоже отвалится. Не наблюдал такого?

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

наблюдал, кстати, и сервер засыпал( если его по ssh запускать

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

а это ничего не значит. write вернёт количество байт которое влезло в буфера ядра. Это не значит что эти данные дойдут до получателя.

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

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

нет, тачки в разных углах города

Кстати, это ведь не локальная сеть. Вам провайдер(ы) разве обещал(и) стабильное соединение двух компов?

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

да нет, ошибки точно нет в исходниках

*адский смех*

Думаю жизнь тебе ещё не раз докажет, что нельзя ни в чём до конца быть уверенным.

Хотя в данном случае наиболее вероятно, что проблема именно в самой сети (NAT-ы или ещё что-нибудь).

pathfinder ★★★★ ()

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

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

Потестируй на локалхосте, обычно обвинения в сторону 3х программ типа натов, компиляторов, библиотек итд не проходят проверок ;)

Программа многопоточная?

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

Я откуда знаю? Я отвечаю на вопрос топикстартера :)

Vamp ()
Ответ на: комментарий от kabanchik

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

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

>> fork() на каждый коннект

Оффтоп. Вообще так не надо. Это плохо.

Обычная техника. Например. такую использует Postgres, SSH и куча Ъ-Unix программ. Или ты ничего не видел, кроме Web-серверов?

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

Думаю там каждый такой форк умеет много коннектов обслуживать, кроме ssh, там действительно так логичнее. Такой подход кроме простоты и изоляции процессов ничего особенно не дает, кроме неудобства взаимодействия, шарить все ручками надо. Если есть возможность, особенно для софта с большим количеством длительный соединений лучше использовать epoll и его друзей в других ОС

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

> Думаю там каждый такой форк умеет много коннектов обслуживать

Нет.

Такой подход кроме простоты и изоляции процессов ничего особенно не дает,

Как будто этого мало.

кроме неудобства взаимодействия, шарить все ручками надо.

Зависит от задачи. Тебе всё кажется вебелью.

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

Понятно что зависит от задачи. Почему тебе кажется что ты знаешь что мне кажется? Просто если процессы не взаимодействуют особо, то можно и форкать. Иначе это просто глупо себя ограничивать. В линукс все равно процессы и потоки одинаково описываются в ядре, просто парочка флажков других. Но каких флажков. «Я прошу продублировать с помощью COW мое адресное пространство». Это блин вообще бред, только выглядит так мило в коде. Начинешь писать что-то сложнее и нагруженнее (или наоборот много висящих соединений), то даже легковеснейшие потоки, без единого копированого пускай даже через COW, становятся слишком дорогими. Это не ssh, который друг с другом не взаимодействует, идеально ложится на парадигму parent-child и потом все равно другой процесс дергает. И главное чтобы сегфолт в одном не валил остальные

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

> Почему тебе кажется что ты знаешь что мне кажется?

По тому, что ты говоришь.

Просто если процессы не взаимодействуют особо, то можно и форкать.

Совсем недавно ты говорил «не делай так вообще, это плохо».

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

Это thumb rule. Обычно люди не понимаю что форк подходит в 5% случаев

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