Тут недавно столкнулся с такой интересной ситуацией.
Есть программа-демон, которая слушает порт и при появлении клиента вызывает fork() а сама опять слушает. Потомок открывает соединение с определенным адресом и представляет собой прозрачный прокси-сервер между клиентом и тем сервером. В конце сеанса оба сокета (с клиентом и с сервером) закрываются и потомок завершается по exit(0).
Это описание алгоритма работы программы. Теперь, собственно, ситуация. Закрытый в потомке сокет, который был получен от папы, остается открытым в папе. В связи с этим, через некоторое время папа начинает говорить "Too many open files". С другой стороны, недавно помогал писать сетевую программу, по началу схожую с этой. Там такого не наблюдается - сокет, закрытый в потомке, закрывается и в папе.А теперь вопрос - как и в каких ситуациях всё это работает ?
Пока проблема решилась примерно так:
...
int ClientSocket=accept(...);
... N проверок и разблокирование сокета ...
switch (fork()) {
case -1: ошибка
case 0: потомок
default: sleep(1); close(ClientSocket);
};
...При этом потомок продолжает работать как ни в чем не бывало.
Тут несколько моментов:
1) клиентский сокет нужно в "папе" закрывать СРАЗУ после fork(). Это наиболее правильно.
sleep() ставить не рекомендую. И код захламляется и выгоды никакой.2) потомок рекомендуют завершать вызовом _exit(2) а не exit(3). А если используется vfork () то ТОЛЬКО _exit(2).
3) во втором случае (когда сокет, закрываемый в потомке, закрывается и в "папе") вероятно используется не fork(), а vfork(). В этом случае потомок живёт в адресном пространстве родителя и имеет доступ ко всем его ресурсам.
P.S. Лучший источник по использованию сокетов - Unix Network Programming (R.Stevens). Если можешь достать - очень пригодится.
В принципе, я так и понял, но вот в другой програмке все работает через fork и без закрытия сокета в папе. Хотя может быть я этот close просто и не заметил.
Все равно спасибо. Теперь хоть определился, что у меня это работает правильно :))>P.S. Лучший источник по использованию сокетов
>- Unix Network Programming (R.Stevens).
>Если можешь достать - очень
>пригодится.Искал на бумаге - не нашел. Может url есть какой ?
К сожалению Stevens-a я в электронном виде не нашёл.
Некоторые полезные ссылки по сокетам можно найти здесь:
http://www.lowtek.com/sockets/
Спасибо, посмотрим :))
Мне кажется: "сокет, закрытый в потомке, закрывается и в папе" -такого не может быть.
Если потомок - новый процесс, то это свое
адресное пространство, значит что-бы мы не делали
в потомке, это не будет влиять на родителя.
Все это справедливо если переменная не в разделяемой память и если это процесс а не pthread, кроме этого, если переменная не указатель, в этом случае могут быть неожиданности.
Новый сокет нужно закрывать в родителе.
>Мне кажется: "сокет, закрытый в потомке,
>закрывается и в папе" -такого
>не может быть.
Тем не менее, я такое наблюдал.> Если потомок - новый процесс, то это свое
> адресное пространство, значит что-бы мы не
> делали в потомке, это не будет влиять на
> родителя.Вот ситуация, показывающая, насколько тесно связаны потомок и родитель, работающие с потоками данных.
Программа открывает файл и создает потомка. Потомок читает что-то из файла, закрывает его и выходит. После этого родитель читает чего-то из файла, закрывает его и выходит. Так вот, если потомок прочитал, например, 10 байт, начиная с 0-го смещения, то родитель прочтет данные, которые начинаются с 10-го смещения.