Базовый сервер потребляет огромные ресурсы ЦП - как облегчить?

Я пишу довольно простой сервер на С++.

Я получил архитектуру, подобную этой:

Один поток (сервер) постоянно зацикливается на accept(), ожидая подключения (docs).

Каждое обнаруженное соединение создает поток, который зацикливается на recv() ожидании чтения и send(), который отправляет что-либо из своей очереди (получить документы), (отправить документы).

Тем не менее, я хочу иметь возможность (из внешнего потока) сообщить серверу или отдельным соединениям, чтобы они по существу убили себя. Проблема в том, что accept() и recv() оба блокируются до тех пор, пока не обнаружат какую-либо активность, поэтому у них нет возможности проверить, установлен ли их элемент should_kill_self или что-то в этом роде. Поэтому, чтобы исправить это, я назвал fcntl(sock_fd, F_SETFL, O_NONBLOCK) файловых дескрипторов, чтобы они этого не делали.

Таким образом, у меня есть сервер, постоянно перебирающий accept() и проверяющий should_kill_self, и у меня есть каждое соединение, перебирающее recv(), проверяющее, есть ли что-нибудь в очереди к send(), и проверяющее should_kill_self.

Таким образом, я могу подать им сигнал убить себя в любое время, но побочный эффект, который я заметил, заключается в том, что они берут на себя огромные объемы обработки. Мне интересно, делаю ли я с этой настройкой что-то глупое, что приводит к избыточным вычислениям. Мне ВООБЩЕ не нужно, чтобы это был сервер со сверхнизкой задержкой, так что «правильный» способ облегчить это, например, спать в течение 10 секунд между каждым циклом?

Я новичок в написании сетевого кода, поэтому я почти уверен, что просто делаю что-то глупое. Любой совет будет принят с благодарностью!


person Phildo    schedule 31.10.2014    source источник
comment
Правильный способ - использовать выбор или опрос.   -  person Max    schedule 31.10.2014
comment
Используйте select и не создавайте поток для каждого входящего соединения. из которых захватывает элемент из очереди, обрабатывает и повторяет.   -  person Jerry Coffin    schedule 31.10.2014


Ответы (1)


Вероятно, вам нужно изучить неблокирующий ввод-вывод в Linux или порты завершения ввода-вывода в Windows. См. здесь и здесь.

Их программирование требует дополнительных усилий и немного сложнее, чем программирование простого сервера сокетов. Тем не менее, существуют библиотеки, которые обертывают неблокирующий ввод-вывод (и IOCP) и предоставляют простой интерфейс для использования. Одним из примеров является ASIO в Boost. Есть много других библиотек даже для Java и других языков.

person hebbo    schedule 31.10.2014