Гарантируется ли, что дескрипторы сокетов в linux / freebsd будут иметь почти последовательные или сопоставимые номера?

#c #c #linux #sockets

#c #c #linux #сокеты

Вопрос:

Я понимаю, что ничто не мешает linux присваивать дескрипторам любые случайные числа в диапазоне 0 … 2 ^ 32 при создании нового сокета. Но какова реальность? В моем приложении (веб-сервере) мне нужна структура сопоставления, которая отображает дескриптор в «структуру соединений». Я понимаю, что какое-то RB-дерево (int -> connection_ptr *) будет работать, но линейный массив указателей connection_ptr (где каждый указатель помещается в offset (index) = значение дескриптора) будет немного быстрее.

Комментарии:

1. Вы можете использовать хэшированный контейнер типа std::unordered_map (возможно, с пользовательским хэшером), чтобы получить как экономию места, так и очень быстрый доступ.

2. Ничего не гарантируется

3. Я знаю, что вы спрашивали о Linux, но дескрипторы сокетов — это указатели в Windows, а не целые числа, поэтому они определенно не являются плотными в пространстве, поэтому любое решение, предполагающее, что они есть, не будет переноситься.

4. @EJP: Это зависит от того, какую реализацию стандартной библиотеки вы используете, но невозможно select предоставить, если они не являются целыми числами.

Ответ №1:

Файловые дескрипторы всегда назначаются с наименьшего доступного номера. Это гарантируется POSIX.

Комментарии:

1. Это для всего процесса или для всего компьютера? То есть, если у меня есть несколько других приложений, работающих и создающих / уничтожающих сокеты, я ожидал бы иметь (потенциально большие) пробелы с точки зрения одного приложения.

2. @MatthieuM. Для всего процесса. Файловые дескрипторы не имеют никакого значения вне процесса, который их создал.

3. Было бы здорово, если бы Windows-парень мог взвесить и сказать нам, если там то же самое.

4. @midor: насколько я понимаю, ответ отрицательный для функций, подобных псевдофайловым дескрипторам, предоставляемых в MSVCRT, но, конечно, да, если вы используете слой POSIX в Windows, такой как Cygwin, Interix и т. Д.

Ответ №2:

Даже если бы это было реализовано таким образом, если вы заботитесь о переносимости и надежности, вы не можете полагаться на это.

Чтобы получить почти постоянную сложность доступа, вы можете использовать хэшированный контейнер, например std:unordered_map . Вы даже можете написать пользовательский хэшер, чтобы хранилище было оптимизировано для распределения номеров файловых дескрипторов.

 struct SocketHasher {
    size_t operator()(uint32_t key) {
        return key amp; 0xFFFF;
    }
}
std::unordered_map<uint32_t, connection_ptr, SocketHasher> connectionPool;
  

Комментарии:

1. Зачем мне нужен пользовательский хэшер?

2. Вы можете использовать его для лучшего распределения сокетов между сегментами карты, если вы знаете, как генерируются сокеты #. Однако эта часть полностью необязательна, и я предполагаю, что код будет хорошо работать и без нее.

3.Этот ответ неверен. Файловые дескрипторы определены таким образом, что они назначаются минимально доступным способом. Они не являются абстрактными дескрипторами, и вам не нужно обращаться с ними как с таковыми. (Примечание: контракт с открытым интерфейсом select требует, чтобы вы выполняли числовые сравнения (операция max) для файловых дескрипторов, и не работает, если все дескрипторы не находятся в фиксированном диапазоне от 0 до FD_SETSIZE-1 ).