Сокет-сервер с epoll и потоками

Я пытаюсь создать сервер сокетов на C для совместного редактирования в реальном времени http://en.wikipedia.org/wiki/Collaborative_real-time_editor, но я не знаю, какая архитектура сервера для этого лучше всего.

Сначала я пытался использовать select для сервера сокетов, но после этого я читал об epoll и теперь думаю, что epoll — лучший выбор, потому что клиент будет отправлять каждое письмо, которое пользователь напишет в textarea, на сервер, поэтому у сервера будет достаточно данных для обработки.

Кроме того, я хочу использовать потоки с epoll, но я точно не знаю, как их использовать. Я хочу использовать потоки, потому что считаю, что лучше использовать 2 или все процессоры на целевой машине.

Мой план

  • создать 2 потока при запуске сервера

  • первый поток проанализирует новых клиентов и подготовит их к чтению или отправке

  • второй поток будет иметь задание на чтение и отправку данных от/к клиентам

Проблема в том, что эти 2 потока будут использовать while(1) с epoll_wait.

Мои вопросы: это хорошая архитектура сервера для использования epoll с потоками? Если нет, то какие варианты у меня есть?

EDIT: я не могу использовать libevent или libev или другие библиотеки, потому что это проект колледжа, и мне не разрешено использовать внешние библиотеки. .


person cemycc    schedule 28.11.2011    source источник
comment
Я бы посоветовал не использовать epoll из-за того, что он не является общедоступным, и что вы начинаете с чего-то простого при выяснении архитектуры. Кроме того, epoll хорош, если у вас большое количество подключений, но это не имеет большого значения, когда дело доходит до времени отклика, когда у вас всего несколько подключений.   -  person Some programmer dude    schedule 28.11.2011
comment
если вам не удалось насытить одно ядро ​​ЦП, нет причин использовать многопоточность. и для этого вам нужно 10 тысяч клиентов (если ваше приложение хорошо написано).   -  person Karoly Horvath    schedule 29.11.2011


Ответы (3)


Я думаю, вы пытаетесь усложнить эту проблему. Архитектура epoll в Linux была предназначена для ситуаций, когда у вас есть тысячи одновременных подключений. В таких случаях накладные расходы, связанные с определением системных вызовов poll и select, будут основным узким местом на сервере. Решение использовать poll или select против epoll основано на количестве подключений, а не на объеме данных.

Для того, что вы делаете, кажется, что люди в вашей системе редактирования сойдут с ума после того, как вы нажмете несколько десятков одновременных редакторов. Использование epoll, вероятно, сведет вас с ума; они проделывают несколько трюков с API, чтобы выжать дополнительную производительность, и вы должны быть очень осторожны, обрабатывая информацию, которую вы получаете в ответ на вызовы.

Такое приложение выглядит так, как будто оно связано с сетевым вводом-выводом, а не с процессором. Я бы попробовал сначала написать его как однопоточный сервер с poll. Когда вы получаете новый текст, при необходимости буферизируйте его для своих клиентов, а затем отправьте его, когда сокет примет вызовы write. Используйте неблокирующий ввод-вывод; единственный вызов, который вы хотите заблокировать, — это вызов poll.

Если вы выполняете значительный объем обработки данных после их получения, но перед отправкой обратно клиентам, вы можете извлечь выгоду из многопоточности. Сначала напишите однопоточную версию, а затем, если вы привязаны к ЦП (проверьте с помощью top) и большая часть времени ЦП тратится на функции, в которых вы выполняете обработку данных (проверьте с помощью gprof), добавьте многопоточность для обработки данных. .

Если вы хотите, вы можете использовать каналы или сокеты домена Unix внутри программы для связи между различными потоками --- таким образом, все в основном потоке может управляться событиями и обрабатываться через poll. Кроме того, с этой моделью вы даже можете использовать несколько процессов с fork вместо нескольких потоков.

person David Brigada    schedule 17.12.2011

Возможно, вы захотите использовать что-то вроде libev или libevent вместо написания собственной реализации обработки событий. они дают вам кроссплатформенный обработчик событий, который будет использовать все подходящее (будь то select, poll, epoll, kqueue или что-то еще) и, скорее всего, с меньшими накладными расходами, чем когда два потока передают работу друг другу.

person Hasturkun    schedule 28.11.2011
comment
Как тогда можно использовать libeven или libev для использования всех доступных процессоров? есть ли стандартный способ сделать это? - person SlappyTheFish; 28.11.2011
comment
@SlappyTheFish: Насколько я понимаю, в этом нет необходимости. даже довольно наивная реализация select, скорее всего, будет работать, поскольку она в основном связана с вводом-выводом. также, предполагая TCP, проблема отправки каждого письма отдельно на самом деле не существует (если не принудительно, например, с использованием TCP_NODELAY или аналогичного). - person Hasturkun; 28.11.2011
comment
@Hasturkun Я забыл упомянуть в своем основном посте, что я не могу использовать libevent или libev, потому что это проект колледжа, и мне не разрешено использовать какие-либо внешние библиотеки. - person cemycc; 28.11.2011
comment
@bugspy.net Они учат нас только простому C, например, это был год, когда они добавили epoll, в последние годы не было упоминания об epoll, только select и poll. :) - person cemycc; 29.11.2011
comment
@cemycc: простой однопоточный сервер, вероятно, подойдет для этого случая, если только от вас не требуется поступать иначе. вы можете использовать один и тот же цикл select или poll как для приема новых подключений, так и для отправки/получения данных из подключенных сокетов. Я предлагаю вам настроить ваши сокеты как неблокирующие, чтобы предотвратить некоторые неожиданности (например, select указывает, что recv не будет блокироваться, но последующие recv блокируются, что может произойти для UDP) - person Hasturkun; 29.11.2011

Просто начните использовать libevent или libev и следуйте их примеру. Примеров множество - не пытайтесь изобретать здесь что-то новое

person GabiMe    schedule 28.11.2011
comment
Иногда попытка сделать это самостоятельно может заставить человека оценить сложность системы и больше оценить простоту использования API, а также уменьшить возможные сюрпризы, которые возникают при использовании API более высокого уровня. Если это проект колледжа, я бы посоветовал использовать необработанный опрос/выбор/epoll! - person Aktau; 24.04.2013