Как написать Main-Loop для сервера? - PullRequest
3 голосов
/ 10 сентября 2011

У меня есть простой fcgi-сервер, написанный на c ++ - сейчас он однопоточный.Например, я видел основной цикл, например

accept_connections();
handle_data();`
handle_connections();

, но что, если я хочу отвечать каждому клиенту одновременно?Потому что, если я это понимаю, сервер сначала принимает новые соединения, перебирает их и обрабатывает каждое.Но это может быть не очень хорошо, например, из-за загрузки (когда один клиент загружает, другие должны ждать.) Или из-за DoS, как slowloris.Как сервер может работать с несколькими клиентами одновременно?Я видел один сервер, он был однопоточным - и сделал это.

Как это сделать?

Ответы [ 3 ]

2 голосов
/ 27 сентября 2012

Я решил это раньше, но хочу ответить на мой вопрос.

Решение, которое я принял:

  • 1 поток акцептора - (accept () для новоговходящие соединения в режиме блокировки) и назначение соединений сетевым потокам с балансировкой нагрузки
  • N сетевых потоков, где N = (1 поток на 1000 клиентов) с неблокирующим поведением:
    • инициализация
    • во время работы сервера
      • установить наблюдателя тайм-аута (для отключения блокировки в цикле событий)
      • запустить цикл событий
      • остановить наблюдателя тайм-аута
      • добавить новые сокеты изпоток-получатель
      • перебирает соединения, запускает Update (), пытается сбросить вывод, проверяет закрытие и т. д., если Update () возвращает -1, удаляет соединение из списка
    • end while
    • освободить и закрыть все соединения и освободить всю выделенную память
    • return
  • Рабочие потоки с семафорами posix, ожидающими задания (пул потоков какуправление)
  • (Оптиonal) Фоновый поток с низким приоритетом для планирования и проверки, удаления, например, токенов, сессий и т. д. Много сна.

Я написал собственный обработчик fastcgi.Я также использовал libev для сетевых потоков, буферизованного и прямого вывода, автоматического пробуждения и отключения события записи.Отладка с помощью Valgrind.Clang clang.

Реакции на другие ответы:

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

И я не использовал boost asio, потому что мне не нравятся фреймворки, и асинхронный ввод-вывод не был тем, который я искал.

2 голосов
/ 10 сентября 2011

Просмотрите Boost.Asio для асинхронного ввода-вывода с использованием одного потока.

0 голосов
/ 10 сентября 2011

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

Существуют альтернативные / лучшие методы, но этот довольно прост, и вы можете продолжать использовать блокирующие сокеты. Следите за проблемами синхронизации при доступе к общим ресурсам из ваших потоков!

...