int
является дескриптором, но сам сокет все еще связан с процессом. Ребенок закрывает сокет прослушивания в основном по соображениям безопасности (ему это не нужно, и если ребенок когда-либо порождает другой процесс, этот процесс также унаследует сокет); серверный процесс закрывает сокет нового соединения, потому что в противном случае соединение будет оставаться открытым до тех пор, пока не завершится серверный процесс (сокет существует до тех пор, пока хотя бы один процесс все еще имеет дескриптор).
Вы хотите либо многопоточность, либо правильный подход к разделяемой памяти. Здесь начинается самое интересное.
Совместное использование памяти между независимыми процессами сопряжено с интересными проблемами, но также предоставляет иные невозможные возможности (например, вы можете перезапустить процесс главного сервера и оставить процессы, обслуживающие открытые соединения, работающими, что трудно сделать правильным, поскольку две разные версии затем служба должна общаться друг с другом, но позволяет беспрепятственно обновлять ее, не отключая клиентов и не прерывая обслуживание).
Распределение памяти между потоками является относительно простым, но потоки используют один и тот же набор файловых дескрипторов, поэтому вы здесь не выигрываете.
Наконец, существует третий вариант: цикл обработки событий, отслеживающий несколько сокетов, уделяя внимание каждому, только если что-то действительно происходит. Посмотрите документацию по функциям select
и poll
.