#c #sockets
#c #сокеты
Вопрос:
Использование библиотеки C sockets в системе Linux…
Когда я делаю вызов accept( )
, он всегда возвращает целое число. STDIN
равно 0. Обычно мой первый вызов accept возвращает 3. После этого они увеличиваются.
Мне было интересно; как accept( )
определить, какое целое число является следующим? Если после еще 2 accept( )
вызовов у меня есть 3, 4 и 5, назначенные подключенным клиентам; что произойдет, когда 4 отключится? Следующее целое число 4 или это 6?
Если бы кто-нибудь мог пролить некоторый свет на это, я, конечно, был бы признателен.
Ответ №1:
Он использует следующий в данный момент неоткрытый файловый дескриптор, такой же, как open()
и другие системные вызовы, возвращающие файловые дескрипторы; dup2()
является чем-то вроде исключения из шаблона. (Файловый дескриптор мог быть недоступен для повторного использования, например, если он был частью сетевого подключения, которое еще не было полностью очищено.) (Обновление: вычеркнутый текст восстанавливает исходную версию ответа. Если файловый дескриптор закрыт, он доступен для повторного использования. Могут возникнуть проблемы с повторным использованием адреса сокета из-за состояний ожидания завершения в TCP / IP — но адрес сокета не является файловым дескриптором.)
Если у вас открыты дескрипторы 1-5, затем закройте 4, следующая операция, подобная open, вернет 4.
Возможно, существуют системы, заботящиеся о безопасности, где это не является шаблоном, но это маловероятно. Одна из причин заключается в том, что существует правильный код для обработки перенаправления ввода-вывода, который основан на закрытии стандартного ввода (файловый дескриптор 0) и следующей операции, подобной открытию, с повторным использованием файлового дескриптора; повторите для стандартного вывода (файловый дескриптор 1).
Комментарии:
1. Итак, тогда в контексте вопроса ‘следующий неоткрытый файловый дескриптор’ 4? Или это 6?
2. Я бы написал «наименьшее доступное», просто чтобы было понятнее. Если 4 отключено shutdown () или удаленный отключен, он еще недоступен. Если 4 является close()d локально, следующий open() / accept () / что угодно будет повторно использовать его (при условии, что используется 0-3).
3. Замечание в скобках неверно. Если a
close(fd)
вернулось успешно, число становится немедленно доступным. Всегда будет использоваться наименьшее доступное число fd. Этого требует POSIX, и модификация «безопасности» для изменения этого поведения фактически сделала бы уязвимыми некоторые правильные и согласующиеся программы, которые полагаются на правильное и стандартное поведение.
Ответ №2:
Короткий ответ таков: не рассчитывайте, что accept выдаст вам целые числа в любом ожидаемом порядке. Неважно, насколько соблазнительно просто, по вашему мнению, это упростило бы ситуацию, если бы это произошло.
То, что возвращает accept, на самом деле является «дескриптором» ресурса ядра, который подключит этот дескриптор к соответствующим драйверам, необходимым для чтения и записи, закрытия, поиска (если возможно). Пул доступных дескрипторов ограничен, поэтому, когда вы закрываете сокет, его дескриптор возвращается в пул и может быть использован повторно.
Комментарии:
1. 1 Некоторые вызовы, например
dup()
, документированы для возврата доступного дескриптора с наименьшим номером. Я не думаю, что вы можете полагаться на этоaccept()
.2. 0,1,2 не всегда «принимаются», и ядро не утруждает себя назначением чего-либо, когда оно «запускает» новый процесс (за исключением PID 1). Они просто наследуются от родительского элемента. Итак, если вы напишете
ls -l /dev/fd/ <amp;- 2>amp;-
, вы увидите, что 0 и 2 отключены от терминала (и, возможно, повторно используютсяls
для чтения списка каталогов).3. Этот ответ неверен. Назначение с наименьшим доступным значением является частью стандарта и на 100% надежно в системах POSIX и всех классических Unices.
Ответ №3:
Он возвращает файловый дескриптор для принятого сокета:
RETURN VALUES
The call returns -1 on error and the global variable errno is set to
indicate the error. If it succeeds, it returns a non-negative integer
that is a descriptor for the accepted socket.
Это дает вам числовое значение, которое вы можете использовать с различными файловыми операциями, и это решается за кулисами.