Сокет сервер с эполлом и потоками - PullRequest
6 голосов
/ 28 ноября 2011

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

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

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

Мой план

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

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

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

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

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

РЕДАКТИРОВАТЬ: Я не могу использовать libevent или libev или другие библиотеки, потому что это проект колледжа, и я не могу использовать внешние библиотеки .

Ответы [ 3 ]

5 голосов
/ 18 декабря 2011

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

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

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

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

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

2 голосов
/ 28 ноября 2011

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

2 голосов
/ 28 ноября 2011

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

...