Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Сети > Ограниченное количество подключений по сокету


Автор: Finalist 2.8.2013, 14:46
Сразу вопрос, потом объяснения... 
Можно ли увеличить параметр FD_SETSIZE без пересборки ядра линукса?

Суть дела - пишу серверную часть для карточной игры. До этого делал запросы по http, больше не хочу.
По сокету и быстрее работает, и лучше получается. 
Столкнулся с проблемой: на дебиане сервер на хочет принимать больше FD_SETSIZE(1024 по.ум.) подключений по сокету...
Нашел файлик(select.h) где можно этот параметр поменять, поменял, перекомпилил, после подключения более 1024 начинают лезть ошибки...
Где-то прочел, что после изменения этого параметра, нужно ядро пересобирать. не очень весело на продакшн ядро пересобирать...
На вин7 этой проблемы нет, там ограничение 16 млн. подключений..
Серверный линукс, и такие ограничения?? кто сталкивался с этим, как решать?

Автор: feodorv 2.8.2013, 18:13
Цитата(Finalist @  2.8.2013,  15:46 Найти цитируемый пост)
как решать?

Уходить с select на http://ru.wikipedia.org/wiki/Epoll smile 

Автор: Finalist 5.8.2013, 16:47
Перехожу на Boost::Asio! даже есть код сетевой части, давно на нее смотрел, но как-то боялся притронуться.
Благодарю за ответ!

Автор: GremlinProg 6.8.2013, 06:56
Цитата(Finalist @  2.8.2013,  16:46 Найти цитируемый пост)
Столкнулся с проблемой: на дебиане сервер на хочет принимать больше FD_SETSIZE(1024 по.ум.) подключений по сокету

Это число подключений на 1 вызов select, т.е. "грубо" говоря, это число подключений в какой-то один момент времени, причем для select имеется 3 таких набора, или 2 в дуплексе (read+write=2*FD_SETSIZE). Мне тяжело представить софт, который работает с таким количеством сокетов одновременно ))

Попробуйте изменить логику программы.

Добавлено через 4 минуты и 30 секунд
Цитата(Finalist @  2.8.2013,  16:46 Найти цитируемый пост)
На вин7 этой проблемы нет, там ограничение 16 млн. подключений..

на Windows FD_SETSIZE равен 64 и этого должно быть достаточно!

Автор: Finalist 6.8.2013, 12:24
Цитата(GremlinProg @  6.8.2013,  06:56 Найти цитируемый пост)
софт, который работает с таким количеством сокетов одновременно

Сервер игры в карты, у меня в турнире участвуют 2000 человек... должны участвовать.. 

Автор: GremlinProg 6.8.2013, 12:59
Цитата(Finalist @  6.8.2013,  14:24 Найти цитируемый пост)
у меня в турнире участвуют 2000 человек

ключевое слово: 
Цитата(GremlinProg @  6.8.2013,  08:56 Найти цитируемый пост)
одновременно


интересно посмотреть на латентность такого сервера ))

Вы серьезно думаете, что он адекватно будет работать с таким количеством пользователей? Я в смысле, что такое количество хостов вполне годится для DoS'а на протоколе не многим проще ICMP, не говоря уже о какой-то игровой логике.

Добавлено через 3 минуты и 1 секунду
не то,чтобы я сомневаюсь в Ваших способностях, но сам факт засунуть все 2000 сокетов в один select говорит о том, что все запросы Вы будете обрабатывать последовательно, а это ни как не располагает к работе с таким числом клиентов

Автор: Finalist 6.8.2013, 13:23
Я не пришел сюда показывать свои способности.
Я пришел за советами от знающих людей! Вот у меня задача сделать онлайн карты с турнирами.. 
Помимо всех пользователей которые просто играют друг с другом, мне нужно сделать систему турниров. В турнире должны участвовать от 20 до 2000 тысяч человек.
Есть, конечно, мысль разделить на несколько физических серверов.. распределить турниры по разным серверам, и конектить ребят туда, куда им положено.
Но и это не решает проблемы 2000 игроков турнира.
Прям сейчас занимаюсь тестами epoll, буду по результатам решать на чем оставаться. Но даже бывает такое, что я изначально все делаю неправильно! И если у кого нибудь есть в этом опыт или какие знания, прошу делится чем не жалко, примеры кода не нужны, нужна только философия построения таких систем.
Есть же, пиратки линейки, варкрафта.. с онлайном в до 5000 игроков, как-то же они это сделали?

Автор: GremlinProg 6.8.2013, 14:19
А я не говорю, что нельзя работать с 2000 игроков, можно и больше, но опрашивать в select 2000 сокетов неоптимально. У Вас скорее всего даже потребности такой не будет, если грамотно спланировать сервер.

На сервере заведите для каждого сокета флаг готовности для чтения/записи. После select'а, для отфильтрованных сокетов сбрасывайте соответствующие флаги готовности и обрабатывайте для них соответствующее действие (можно на пуле потоков). Как только действие завершено - устанавливайте соответствующий флаг готовности обратно.

А для выбора наборов fd_set проходите по всему списку сокетов и смотрите на флаги готовности: если сокет готов к чтению - кидайте его в "набор чтения", к записи - в "набор записи". Если оба флага опущены, значит какой-то из потоков сервера в данный момент работает с данным сокетом, и пытаться вызвать для этого сокета select бессмысленно. Т.е., такие сокеты надо пропускать.

Вот по такой схеме и определите, какая доля сокетов у Вас действительно требует вызова select. Наберется больше FD_SETSIZE - пусть оставшиеся чуть подождут (до следующего вызова select). Если латентность, формируемая таким образом начнет превышать какую-то критическую массу, значит для вашей игры и вашего "физического" сервера достигнут максимум и можно думать о расширении логики на дополнительные "физические" ресурсы (ресурсов самого сервера или их числа).

Автор: akizelokro 6.8.2013, 17:40
Цитата(Finalist @  6.8.2013,  13:23 Найти цитируемый пост)
Есть же, пиратки линейки, варкрафта.. с онлайном в до 5000 игроков, как-то же они это сделали? 


Все писали многопользовательские игровые сервера. Никто не держит сеансы игры всё время соединёнными. Пишешь периодичность опроса клиентом сервера, клиент обратился, передал серверу информацию о себе, получил обновлённую информацию, отсоединился.  
Хотя, можбыть есть и такие игры, где постоянный обмен. Значит, я опять лопухнулся  smile 

Кстати, по онлайн-картам я не лопухнулся. потому что писал. Там как раз не нужно постоянное соединение.
Там можешь вообще обмен ходами свалить на клиентов, пусть устанавливают соединение друг с другом, а на сервере будешь им производить сдачу, чтобы никто не хакнул твоих клиентов. Если нужна запись партии, раз в определённое время скидывай от одного из клиентов (или ото всех) запись ходов.


Автор: feodorv 6.8.2013, 20:07
Цитата(Finalist @  6.8.2013,  14:23 Найти цитируемый пост)
Прям сейчас занимаюсь тестами epoll

Напишите, пожалуйста, как оно Вам  smile 

Автор: Finalist 7.8.2013, 12:12
Цитата(GremlinProg @  6.8.2013,  14:19 Найти цитируемый пост)
На сервере заведите для каждого сокета флаг готовности для чтения/записи

Пока что, использую Qt Network, там нет никаких циклов для обработки сокета, мне приходит сигнал readyRead() с указателем на сокет который готов читаться.. читаю, парсю, отвечаю, и дальше выхожу в цикл обработки событий, и дальше ожидаю сигнал.
Теперь перейду на Boost::Asio там та же картина.. пришел сигнал, мне в callback пришел вызов. меня напрягает само ограничение по соединениям. На следующей неделе напишу результаты!
Цитата(akizelokro @  6.8.2013,  17:40 Найти цитируемый пост)
обмен ходами свалить на клиентов, пусть устанавливают соединение друг с другом, а на сервере будешь им производить сдачу

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

Автор: SVN74 7.8.2013, 12:28
Цитата(Finalist @  7.8.2013,  12:12 Найти цитируемый пост)
Цитата(akizelokro @  6.8.2013,  17:40 )
обмен ходами свалить на клиентов, пусть устанавливают соединение друг с другом, а на сервере будешь им производить сдачу

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


Может вам поможет IPv6 туннелирование?

Автор: feodorv 7.8.2013, 13:09
Цитата(SVN74 @  7.8.2013,  13:28 Найти цитируемый пост)
Может вам поможет IPv6 туннелирование? 

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

Автор: GremlinProg 7.8.2013, 13:30
Цитата(Finalist @  7.8.2013,  14:12 Найти цитируемый пост)
Пока что, использую Qt Network, там нет никаких циклов для обработки сокета, мне приходит сигнал readyRead() с указателем на сокет который готов читаться.. читаю, парсю, отвечаю, и дальше выхожу в цикл обработки событий, и дальше ожидаю сигнал.Теперь перейду на Boost::Asio там та же картина..

Похоже, Вы меня не поняли! Я Вам предлагаю завести флаг готовности сокета к select, чтобы Вам не мешал порог FD_SETSIZE, а сервера Qt и Boost вызывают select сами, без Вашего участия, поэтому как-то повлиять на планирование сетевой нагрузки для таких серверов с "постоянным подключением клиентов" будет проблематично. По крайней мере, мне оценить их гибкость сложно, т.к. я ими не пользовался.

"Вытащите" понятные исходники этих серверов - посмотрим, может не все так печально.

Автор: Finalist 19.9.2013, 15:17
Всем привет!
Цитата(feodorv @  7.8.2013,  13:09 Найти цитируемый пост)
Друзья, epoll должен решить все проблемы

Все таки Boost::Asio решили мои проблемы. Была конечно еще одна запара, но решилась легко и быстро.
Значит, взял я пример и сделал на его основе свой серв. http://www.boost.org/doc/libs/1_39_0/doc/html/boost_asio/example/echo/async_tcp_echo_server.cpp

запустил, все норм, но ограничение в 1024 все равно присутствовало!
Код

void server::handle_accept(session* new_session,
    const boost::system::error_code& error)
{
  if (!error){accept again..}
  else {cout << error.message()} // тут пишет too many open files

пишет too many open files!
начал искать.. нашел! 
в файл /etc/security/limits.conf
нужно добавить две строки
Код

root soft nofile 65535 # мне хватает 65 тыщ подключений... набрать бы столько)
root hard nofile 65535

в файл  /etc/pam.d/common-session
добавляем строку 
Код

session required pam_limits.so


потом запускаем
Код

ulimit -n 65535 # можно меньше
ulimit -n или ulimit -a

и наслаждаемся цифрой!
проверял на цифре 4096 все прекрасно работает, подключилось 4088 сокетов, и подключения прекратились, видать остальные дескрипторы были открыты где-то еще...
Кстати, пришлось отказаться от Qt полностью, ибо io_service::run() и QCoreApplication::exec() взаимозаменяемы, запустить их можно только по очереди.
нашел хороший учебник на хабре про сигналы слоты в Boost::Signals2 - отлично работают. Контейнеры использую из набора STL
Если есть вопросы, задавайте!

Автор: feodorv 19.9.2013, 16:04
Прекрасно, мои поздравления smile 

Автор: Finalist 19.3.2014, 20:49
Если кому интересно, я нашел как поднять количество подключений на Qt
https://github.com/sjinks/qt_eventdispatcher_libev
очень быстрый, и огромное количество подключений. Так, что я вернулся на Qt и продолаю писать сервер на нем. Нашел либу давно, только сейчас вспомнил, что можно сюда заинформить... 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)