URL: https://www.opennet.me/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID9
Нить номер: 131
[ Назад ]

Исходное сообщение
"Кто бы мне объяснил по форкам и сокетам (Linux 2.x.x)"

Отправлено XMan , 25-Авг-01 18:32 
Тут недавно столкнулся с такой интересной ситуацией.
Есть программа-демон, которая слушает порт и при появлении клиента вызывает fork() а сама опять слушает. Потомок открывает соединение с определенным адресом и представляет собой прозрачный прокси-сервер между клиентом и тем сервером. В конце сеанса оба сокета (с клиентом и с сервером) закрываются и потомок завершается по exit(0).
Это описание алгоритма работы программы. Теперь, собственно, ситуация. Закрытый в потомке сокет, который был получен от папы, остается открытым в папе. В связи с этим, через некоторое время папа начинает говорить "Too many open files". С другой стороны, недавно помогал писать сетевую программу, по началу схожую с этой. Там такого не наблюдается - сокет, закрытый в потомке, закрывается и в папе.

А теперь вопрос - как и в каких ситуациях всё это работает ?

Пока проблема решилась примерно так:
...
int ClientSocket=accept(...);
... N проверок и разблокирование сокета ...
switch (fork()) {
  case -1: ошибка
  case  0: потомок
  default: sleep(1); close(ClientSocket);
};
...

При этом потомок продолжает работать как ни в чем не бывало.


Содержание

Сообщения в этом обсуждении
"RE: Кто бы мне объяснил по форкам и сокетам (Linux 2.x.x)"
Отправлено romanSA , 27-Авг-01 11:23 
Тут несколько моментов:
1) клиентский сокет нужно в "папе" закрывать СРАЗУ после fork(). Это наиболее правильно.
sleep() ставить не рекомендую. И код захламляется и выгоды никакой.

2) потомок рекомендуют завершать вызовом _exit(2) а не exit(3). А если используется vfork () то ТОЛЬКО _exit(2).

3) во втором случае (когда сокет, закрываемый в потомке, закрывается и в "папе") вероятно используется не fork(), а vfork(). В этом случае потомок живёт в адресном пространстве родителя и имеет доступ ко всем его ресурсам.

P.S. Лучший источник по использованию сокетов - Unix Network Programming (R.Stevens). Если можешь достать - очень пригодится.


"RE: Кто бы мне объяснил по форкам и сокетам (Linux 2.x.x)"
Отправлено XMan , 27-Авг-01 16:48 
В принципе, я так и понял, но вот в другой програмке все работает через fork и без закрытия сокета в папе. Хотя может быть я этот close просто и не заметил.
Все равно спасибо. Теперь хоть определился, что у меня это работает правильно :))

>P.S. Лучший источник по использованию сокетов
>- Unix Network Programming (R.Stevens).
>Если можешь достать - очень
>пригодится.

Искал на бумаге - не нашел. Может url есть какой ?


"RE: Кто бы мне объяснил по форкам и сокетам (Linux 2.x.x)"
Отправлено romanSA , 30-Авг-01 11:48 
К сожалению Stevens-a я в электронном виде не нашёл.
Некоторые полезные ссылки по сокетам можно найти здесь:
http://www.lowtek.com/sockets/

"RE: Кто бы мне объяснил по форкам и сокетам (Linux 2.x.x)"
Отправлено XMan , 31-Авг-01 18:52 
Спасибо, посмотрим :))

"RE: Кто бы мне объяснил по форкам и сокетам (Linux 2.x.x)"
Отправлено grey , 12-Сен-01 18:05 
Мне кажется: "сокет, закрытый в потомке, закрывается и в папе" -такого не может быть.
Если потомок - новый процесс, то это свое
адресное пространство, значит что-бы мы не делали
в потомке, это не будет влиять на родителя.
Все это справедливо если переменная не в разделяемой память и если это процесс а не pthread, кроме этого, если переменная не указатель, в этом случае могут быть неожиданности.
Новый сокет нужно закрывать в родителе.

"RE: Кто бы мне объяснил по форкам и сокетам (Linux 2.x.x)"
Отправлено XMan , 12-Сен-01 18:45 
>Мне кажется: "сокет, закрытый в потомке,
>закрывается и в папе" -такого
>не может быть.
Тем не менее, я такое наблюдал.

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

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

Программа открывает файл и создает потомка. Потомок читает что-то из файла, закрывает его и выходит. После этого родитель читает чего-то из файла, закрывает его и выходит. Так вот, если потомок прочитал, например, 10 байт, начиная с 0-го смещения, то родитель прочтет данные, которые начинаются с 10-го смещения.