Если вы используете Windows, то самый эффективный способ обработки большого количества клиентов - это построить сервер на основе асинхронных портов ввода-вывода и портов завершения ввода-вывода. Это позволяет эффективно обслуживать множество (10 тысяч) клиентов с небольшим количеством потоков (4?).
Некоторые люди считают, что асинхронный характер модели порта завершения ввода / вывода немного сложен для понимания, но у меня есть бесплатная платформа исходного кода C ++, которую вы можете загрузить с здесь , чтобы начать работу. Если вы используете управляемый код, то все API асинхронных сокетов в .Net Framework используют порты завершения ввода / вывода «под капотом».
Модель порта завершения ввода / вывода хорошо масштабируется, потому что это примитив операционной системы, созданный с нуля для обеспечения эффективности; он знает, работают ли связанные с ним потоки или ожидают, и поэтому может управлять количеством потоков, которые он позволяет обрабатывать «завершения» одновременно. Он также использует потоки в порядке fifo, так что если мало работы, то будет меньше переключаемых контекстов, так как будет использовано только минимальное количество потоков (вместо того, чтобы планировать рабочие элементы во всех потоках и вызывать все их стеки). оставаться в памяти). Напротив, ваш собственный пул потоков должен быть менее эффективным, поскольку вы не обладаете тем же уровнем знаний о потоках, что и IOCP. Выбор часто страдает от ограничения количества поддерживаемых сокетов, что означает, что для истинной масштабируемости вам необходимо создать сложный код поверх вашего выбора, чтобы иметь возможность управлять большим количеством клиентов. Использование потока для каждой модели подключения гораздо менее эффективно, поскольку новые потоки не только регулярно запускаются и останавливаются, но и у вас меньше возможностей контролировать количество потоков в процессе одновременно - потоки являются относительно тяжелыми ресурсами, если учитывать в их стековом пространстве и т. д. Как только у вас будет больше потоков, чем ядер ЦП, вы будете терять время на переключение контекста (которого IOCP часто избегает полностью). Наконец, создание нового процесса для каждого соединения является еще более тяжелым, чем для потока на модель соединения, и лично я не вижу причин считать это допустимым вариантом в современной ОС.