Подтвердить что ты не робот

Почему я должен использовать неблокирующие или блокирующие сокеты?

Во-первых, я должен спросить, что является лучшим, в каком состоянии? Например, сервер MMORPG в режиме реального времени. Что делать, если я создаю поток для каждого клиента вместо использования неблокирующих сокетов? Или что, если я использую один поток, содержащий все неблокирующие сокеты? Можете ли вы объяснить мне преимущества?

4b9b3361

Ответ 1

Ваш вопрос заслуживает гораздо более продолжительного обсуждения, но здесь короткий удар по ответу:

  • с использованием блокирующих сокетов означает, что только один сокет может быть активен в любой момент в любом одном потоке (поскольку он блокирует при ожидании активности)
  • Использование блокирующих сокетов обычно проще, чем неблокирующие сокеты (асинхронное программирование имеет тенденцию быть более сложным).
  • вы могли бы создать 1 поток на один сокет, как вы заявили, но потоки имеют накладные расходы и крайне неэффективны по сравнению с неблокирующими решениями;
  • с неблокирующими сокетами вы можете обрабатывать гораздо больший объем клиентов: он может масштабироваться до сотен тысяч в одном процессе, но код становится немного сложнее.

С неблокирующими сокетами (в Windows) у вас есть несколько вариантов:

  • опрос
  • события на основе
  • перекрытие ввода/вывода

Overlapped I/O даст вам лучшую производительность (тысячи сокетов/процессов) за счет того, что это самая сложная модель для правильного понимания и реализации.

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

ПРИМЕЧАНИЕ

Здесь лучшее объяснение того, почему использование модели thread/socket - плохая идея:

В Windows создание большого количества потоков крайне неэффективно, поскольку планировщик не может правильно определить, какие потоки должны получать процессорное время, а какие нет. Это в сочетании с издержками памяти для каждого потока означает, что у вас закончится нехватка памяти (из-за пространства стека) и процессорных циклов (из-за накладных расходов на управление потоками) на уровне ОС задолго до того, как у вас не будет возможности обрабатывать соединения сокетов.

Ответ 2

Я буду говорить, говоря, что почти для всех, кроме игрушечных программ, вы должны использовать неблокирующие сокеты, как само собой разумеющееся.

Блокирующие сокеты вызывают серьезную проблему: если компьютер с другого конца (или любая часть вашего соединения с ним) не работает во время блокирующего вызова, ваш код будет заблокирован до истечения времени ожидания IP-стека. В типичном случае это около 2 минут, что совершенно неприемлемо для большинства целей. Единственный способ 1 прервать этот блокирующий вызов - это прекратить поток, который его создал, но завершение потока само по себе почти всегда неприемлемо, поскольку по существу невозможно его очистить и вернуть все ресурсы был выделен. Неблокирующие сокеты делают тривиальным прерывание вызова, когда/если это необходимо, без каких-либо действий с потоком, который совершил вызов.

Возможно, блокирующие сокеты работают хорошо, если вместо этого вы используете модель с несколькими процессами. Здесь вы просто создаете совершенно новый процесс для каждого соединения. Этот процесс использует блокирующий сокет, и когда/если что-то пойдет не так, вы просто убиваете весь процесс. ОС знает, как очистить ресурсы от процесса, поэтому очистка не является проблемой. У него все еще есть другие потенциальные проблемы: 1) вам в значительной степени нужен монитор процессов, чтобы убивать процессы, когда это необходимо, и 2) нерестование процесса, как правило, довольно дорого, чем просто создание сокета. Тем не менее, это может быть жизнеспособным вариантом, особенно если:

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

1. Ну, технически не единственный возможный способ, но большинство альтернатив относительно уродливы - чтобы быть более конкретным, я думаю, что к тому времени, когда вы добавите код, чтобы понять, что есть проблема, а затем исправить проблему, вы, вероятно, сделали больше дополнительной работы, чем если бы вы использовали неблокирующий сокет.