Крайне необходима Ваша помощь. Потому что самостоятельно уже устал бороться.
Задача:
Организовать ретранслятор. То есть сервер, к которому подключены клиенты посредством TCP. Сервер принимает данные от одного клиента, и просто передает их всем остальным. Данные строковые, от 1кб до 4-х. В секунду может быть до 5 таких пакетов. Текущий вариант, сделан на c# на ассинхронных сокетах. Все прекрасно пока клиентов 50 — 60 ... но как только клиентов становится более 100, то начинаются безбожные задержки в получении данных (раздача сервера) иногда пакеты задерживаются до 10 минут !!! Что крайне не приемлемо, нужно по возсожности почти мгновенная передача.
Начал делать на c++ с применением не блокирующих сокетов. Но при двух телнет подключениях процессор уходит в жесткую нагрузку до 80%, при пяти, процессор перестает отвечть ! ((((
Пытался уйти в другой вариант на IOCP но там еще хуже. Так как задача сверхсрочная а опыта у меня кот наплакал, то так и не смог их завести.
Прошу помощи. Если возможно в чем проблема в данном подходе, и есть ли более удачные варианты реализации мгновенной передачи данных от одного клиента всем. UDP не подходит. Так как клиенты сидят в интернете, а не за одной сеткой.
Re: Нагруженный TCP сервер как и на чем реализовать
S>#include <windows.h>
S>#include <stdio.h>
S>#include <list>
S>#include <time.h>
S>#include <process.h>
S>std::list<SOCKET> clients;
S>#pragma comment(lib,"ws2_32.lib")
S>FILE *log_srvf = NULL;
S>static void log( const char *fmt, ... )
S>{
S> va_list ap;
S> va_start(ap, fmt);
S> vfprintf(log_srvf, fmt, ap);
S> va_end(ap);
S> fflush(log_srvf);
S>}
S>static void recve_line( SOCKET s, std::string& r )
S>{
S> while (1) {
S> char ch;
S> if(recv(s, &ch, 1, 0) == SOCKET_ERROR) // Ошибка здесь, сокет находится в неблокирующем режиме. Вызов recv возвращает управление немедленно в любом случае, независимо пришли данные или нет.
/*
В итоге ты получаешь замкнутый цикл типа while(1){}, вот тебе и загрузка CPU
Если хочешь использовать неблокирующий режим, то нужно пользоваться функциями для ожидания результата WSAAsyncSelect и WSAEventSelect.
Но в твоем случае(глядя на алгоритм работы) вообще нужно использовать блокирующий режим,
т.к. выгоды от неблокирующего режима при такой организации обмена ты не получишь, исключительно один геморой при написании и сопровождении исходников.
Попробуй не вызывать ioctlsocket(listener, FIONBIO, &argp); и увидишь разницу сразу.
*/
S> {
S> continue;
S> }
S> r.append(1, ch);
S> if (ch == '$')
S> break;
S> }
S> log( "receive: %d bytes\n", r.length());
S>}
S>
S>Пытался уйти в другой вариант на IOCP но там еще хуже. Так как задача сверхсрочная а опыта у меня кот наплакал, то так и не смог их завести.
S>Прошу помощи. Если возможно в чем проблема в данном подходе, и есть ли более удачные варианты реализации мгновенной передачи данных от одного клиента всем. UDP не подходит. Так как клиенты сидят в интернете, а не за одной сеткой.
Re[2]: Нагруженный TCP сервер как и на чем реализовать
Здравствуйте, Crackjack, Вы писали:
C>Здравствуйте, stronciy77, Вы писали:
C> В итоге ты получаешь замкнутый цикл типа while(1){}, вот тебе и загрузка CPU C> Если хочешь использовать неблокирующий режим, то нужно пользоваться функциями для ожидания результата WSAAsyncSelect и WSAEventSelect. C> Но в твоем случае(глядя на алгоритм работы) вообще нужно использовать блокирующий режим, C> т.к. выгоды от неблокирующего режима при такой организации обмена ты не получишь, исключительно один геморой при написании и сопровождении исходников. C> Попробуй не вызывать ioctlsocket(listener, FIONBIO, &argp); и увидишь разницу сразу.
Совершенно согласен ... Вот первый вариант код ниже...
После 50 клиентов, начинает тормозить раздача (потому что много медленных соеденений) вот я и вычитал про не блокирующий режим. Теперь совершенно запутался...
Вопрос все тот же, как избавиться от медленных клиентов (то есть как отправлять данные) и никого не ждать ?
Здравствуйте, stronciy77, Вы писали:
S>Всем добрый день,
S>Крайне необходима Ваша помощь. Потому что самостоятельно уже устал бороться.
S>Вот код.
[тут был ужас]
S>Пытался уйти в другой вариант на IOCP но там еще хуже. Так как задача сверхсрочная а опыта у меня кот наплакал, то так и не смог их завести.
почему там хуже? там как раз таки все прекрасно, и ваша задача решается очень быстро.
S>Прошу помощи. Если возможно в чем проблема в данном подходе, и есть ли более удачные варианты реализации мгновенной передачи данных от одного клиента всем. UDP не подходит. Так как клиенты сидят в интернете, а не за одной сеткой.
Если без IOCP то делать методом пула — читаем функицию select
но лин через iocp в сто раз легче чем через select.
ps:
1. не читайте строку побайтово, читайте в буфер и сразу много, и потом из буфера вычитывайте строку.
2. неблокирующие сокеты были придуманы для того чтобы не создавать по потоку на соединение, подумайте как это все сделать в одном потоке.
Re: Нагруженный TCP сервер как и на чем реализовать
я только что тестировал свой проект под нагрузкой — ок. В чём то схоже.
Сделал на boost::asio.
На "чистых" сокетах я тоже раньше делал, но тут быстрее получается. Если не считать чтения манула по asio.
Но с нуля на сокетах ещё больше читать надо и дольше отлаживать.
Re[3]: Нагруженный TCP сервер как и на чем реализовать
Здравствуйте, stronciy77, Вы писали:
S>Вопрос все тот же, как избавиться от медленных клиентов (то есть как отправлять данные) и никого не ждать ?
Встречный вопрос.
Вот у вас есть N быстрый клиентов и M медленных. Вы хотите, чтобы данные валились со скоростью быстрых клиентов. Вопрос, куда вы собираетесь девать данные, которые уже отправлены быстрым клиентам, но еще не отправлены медленным? Учтите при этом, что если данные продолжают валиться, то неотправленные данные будут расти и расти.
P.S. Нагруженным ваш сервер бы был, если бы количество клиентов измерялось тысячами, и данных было бы на пару порядков побольше
Re[2]: Нагруженный TCP сервер как и на чем реализовать
Здравствуйте, maxlosyam, Вы писали:
M>Здравствуйте, stronciy77, Вы писали:
S>>Всем добрый день,
S>>Крайне необходима Ваша помощь. Потому что самостоятельно уже устал бороться.
S>>Вот код.
M>[тут был ужас]
Если покажу IOCP поделку, боюсь вызвать культурологический шок
S>>Пытался уйти в другой вариант на IOCP но там еще хуже. Так как задача сверхсрочная а опыта у меня кот наплакал, то так и не смог их завести.
M>почему там хуже? там как раз таки все прекрасно, и ваша задача решается очень быстро.
Все прекрасно, для тех кто понимает глубину и ширину сокетов
M>Если без IOCP то делать методом пула — читаем функицию select M>но лин через iocp в сто раз легче чем через select.
M>ps: M>1. не читайте строку побайтово, читайте в буфер и сразу много, и потом из буфера вычитывайте строку.
Как это сделать ? M>2. неблокирующие сокеты были придуманы для того чтобы не создавать по потоку на соединение, подумайте как это все сделать в одном потоке.
Думаю ... только не найти получить хоть мало мальский пример, что бы знать куда копать.
Re[2]: Нагруженный TCP сервер как и на чем реализовать
Здравствуйте, AltCtrlDel, Вы писали:
ACD>я только что тестировал свой проект под нагрузкой — ок. В чём то схоже. ACD>Сделал на boost::asio. ACD>На "чистых" сокетах я тоже раньше делал, но тут быстрее получается. Если не считать чтения манула по asio. ACD>Но с нуля на сокетах ещё больше читать надо и дольше отлаживать.
Ясно, я тоже сомтрел на boost но там 60 метров библиотек ... Не суть, для дела не жалко, а как у него с "быстрой" разадчей, то есть если есть куча медленных и куча быстрых клиентов ?
Re[4]: Нагруженный TCP сервер как и на чем реализовать
Здравствуйте, Pzz, Вы писали:
Pzz>Здравствуйте, stronciy77, Вы писали:
S>>Вопрос все тот же, как избавиться от медленных клиентов (то есть как отправлять данные) и никого не ждать ?
Pzz>Встречный вопрос.
Pzz>Вот у вас есть N быстрый клиентов и M медленных. Вы хотите, чтобы данные валились со скоростью быстрых клиентов. Вопрос, куда вы собираетесь девать данные, которые уже отправлены быстрым клиентам, но еще не отправлены медленным? Учтите при этом, что если данные продолжают валиться, то неотправленные данные будут расти и расти.
Pzz>P.S. Нагруженным ваш сервер бы был, если бы количество клиентов измерялось тысячами, и данных было бы на пару порядков побольше
Вот в этом и была трабла самого проекта на асинхронных сокетах в C# !!!
Пул не обработанных данных, рос и рос как гора, и начинались ужастики с задержками ... Уход в С++ ничего не изменил
А мне тысячи не нужно, мне бы хотя бы раздавал как надо (быстрым быстро, медленным медленно) хотя бы для 500 пользователей ! Это мой предел мечтаний !
Но ничего похожего (решение вопроса) уже неделю не могу найти нигде
Re[3]: Нагруженный TCP сервер как и на чем реализовать
Здравствуйте, stronciy77, Вы писали:
M>>почему там хуже? там как раз таки все прекрасно, и ваша задача решается очень быстро.
тут есть куча тем где iocp уже рассосали по пальцам, поищите.
S>Все прекрасно, для тех кто понимает глубину и ширину сокетов
M>>1. не читайте строку побайтово, читайте в буфер и сразу много, и потом из буфера вычитывайте строку. S>Как это сделать ?
а зачем вам вообще вычитывать строку? там команды? читайте по килобайту, и сколько приняли столько и отправляйте. M>>2. неблокирующие сокеты были придуманы для того чтобы не создавать по потоку на соединение, подумайте как это все сделать в одном потоке. S>Думаю ... только не найти получить хоть мало мальский пример, что бы знать куда копать.
вот тут http://www.tenouk.com/Module41.html есть пример сервера на select, все делается в одном потоке. просто почитайте поищите про select.
Re[5]: Нагруженный TCP сервер как и на чем реализовать
Здравствуйте, stronciy77, Вы писали:
S>А мне тысячи не нужно, мне бы хотя бы раздавал как надо (быстрым быстро, медленным медленно) хотя бы для 500 пользователей ! Это мой предел мечтаний !
QoS вам поможет... Регулируйте ширину канала.
Re[2]: Нагруженный TCP сервер как и на чем реализовать
Здравствуйте, Crackjack, Вы писали:
C> В итоге ты получаешь замкнутый цикл типа while(1){}, вот тебе и загрузка CPU
В принципе, маленького вызова sleep с параметром 10 должно хватить для снижения загрузки CPU до приемлемых процентов... Не?
Re[5]: Нагруженный TCP сервер как и на чем реализовать
Здравствуйте, stronciy77, Вы писали:
S>Вот в этом и была трабла самого проекта на асинхронных сокетах в C# !!! S>Пул не обработанных данных, рос и рос как гора, и начинались ужастики с задержками ... Уход в С++ ничего не изменил
Это же не проблема реализации, а тем более, не проблема языка, выбранного для реализации.
Это вопрос о постановке задачи: что делать, если данные поступают быстрее, чем клиенты успевают их потреблять?
S>А мне тысячи не нужно, мне бы хотя бы раздавал как надо (быстрым быстро, медленным медленно) хотя бы для 500 пользователей ! Это мой предел мечтаний !
Кто должен хранить данные, которые еще не розданы медленным клиентам? Каким механизмом это хранилище должно быть защищено от переполнения?
Еще раз, я сейчас обсуждаю ожидаемое поведение программы, а не то, как оно реализовано.
Re[3]: Нагруженный TCP сервер как и на чем реализовать
S>Ясно, я тоже сомтрел на boost но там 60 метров библиотек ... Не суть, для дела не жалко, а как у него с "быстрой" разадчей, то есть если есть куча медленных и куча быстрых клиентов ?
Ну, асинхронные методы то там есть, конечно. А так, от твоей реализации именно твоей задачи зависит. Если "медленные", застревают и не успевают забирать иногда, так у меня для этого случая специально sqlite прикручена в виде внешнего буфера. Для медленных клиентов смотри размер их mtu, может они вообще через GPRS заходят. Не передавай мелкими порциями, накопи хотя бы до mtu*3, а то много полупустых пакетов летать будет.
Re[4]: Нагруженный TCP сервер как и на чем реализовать
Здравствуйте, AltCtrlDel, Вы писали:
S>>Ясно, я тоже сомтрел на boost но там 60 метров библиотек ... Не суть, для дела не жалко, а как у него с "быстрой" разадчей, то есть если есть куча медленных и куча быстрых клиентов ? ACD>Ну, асинхронные методы то там есть, конечно. А так, от твоей реализации именно твоей задачи зависит. Если "медленные", застревают и не успевают забирать иногда, так у меня для этого случая специально sqlite прикручена в виде внешнего буфера. Для медленных клиентов смотри размер их mtu, может они вообще через GPRS заходят. Не передавай мелкими порциями, накопи хотя бы до mtu*3, а то много полупустых пакетов летать будет.
Тут никакого буфера может не хватить через определенное время. А нельзя включить управлением шириной канала в этом случае?
Re[6]: Нагруженный TCP сервер как и на чем реализовать
Здравствуйте, Pzz, Вы писали:
Pzz>Здравствуйте, stronciy77, Вы писали:
S>>Вот в этом и была трабла самого проекта на асинхронных сокетах в C# !!! S>>Пул не обработанных данных, рос и рос как гора, и начинались ужастики с задержками ... Уход в С++ ничего не изменил
Pzz>Это же не проблема реализации, а тем более, не проблема языка, выбранного для реализации.
Pzz>Это вопрос о постановке задачи: что делать, если данные поступают быстрее, чем клиенты успевают их потреблять?
Пробрасывать все данные которые не успел получить пользователь, то есть не получил лови следующий пакет ! ( К сожалению это единственных выход.)
Не создавать же для каждого пользователя пул сообщений и раздавать с него ? Тогда подтврждение получения будет потреблять еще больше ресурсов !
Вот такое ожидаемое поведение, что успел, то и получил
Re[3]: Нагруженный TCP сервер как и на чем реализовать
Здравствуйте, Nikolay_Ch, Вы писали:
N_C>Здравствуйте, Crackjack, Вы писали:
C>> В итоге ты получаешь замкнутый цикл типа while(1){}, вот тебе и загрузка CPU N_C>В принципе, маленького вызова sleep с параметром 10 должно хватить для снижения загрузки CPU до приемлемых процентов... Не?
Программирование на слипах... Обожаю
Зачем нагревать зазря Вселенную, если можно просто ждать на каком-то объекте? Плюс слип-алгоритмы имеют обычай давать граблей по лбу при выходе измененной архитектуры проца: многоядерность, реордеринг, спин-локи...
Re: Нагруженный TCP сервер как и на чем реализовать
Здравствуйте, stronciy77, Вы писали:
S>Всем добрый день,
S>Крайне необходима Ваша помощь. Потому что самостоятельно уже устал бороться. S>Задача: S>Организовать ретранслятор. То есть сервер, к которому подключены клиенты посредством TCP. Сервер принимает данные от одного клиента, и просто передает их всем остальным. Данные строковые, от 1кб до 4-х. В секунду может быть до 5 таких пакетов. Текущий вариант, сделан на c# на ассинхронных сокетах. Все прекрасно пока клиентов 50 — 60 ... но как только клиентов становится более 100, то начинаются безбожные задержки в получении данных (раздача сервера) иногда пакеты задерживаются до 10 минут !!! Что крайне не приемлемо, нужно по возсожности почти мгновенная передача.
S>Начал делать на c++ с применением не блокирующих сокетов. Но при двух телнет подключениях процессор уходит в жесткую нагрузку до 80%, при пяти, процессор перестает отвечть ! ((((
S>Вот код.
У тебя в коде не используются неблокирующие сокеты. Прочитай про pool/epool и сделай через него. Либы, которые оборачивают это дело libevent, boost::asio и 9000 других.
Sic luceat lux!
Re[5]: Нагруженный TCP сервер как и на чем реализовать
Здравствуйте, Nikolay_Ch, Вы писали:
N_C>Здравствуйте, AltCtrlDel, Вы писали:
S>>>Ясно, я тоже сомтрел на boost но там 60 метров библиотек ... Не суть, для дела не жалко, а как у него с "быстрой" разадчей, то есть если есть куча медленных и куча быстрых клиентов ? ACD>>Ну, асинхронные методы то там есть, конечно. А так, от твоей реализации именно твоей задачи зависит. Если "медленные", застревают и не успевают забирать иногда, так у меня для этого случая специально sqlite прикручена в виде внешнего буфера. Для медленных клиентов смотри размер их mtu, может они вообще через GPRS заходят. Не передавай мелкими порциями, накопи хотя бы до mtu*3, а то много полупустых пакетов летать будет. N_C>Тут никакого буфера может не хватить через определенное время. А нельзя включить управлением шириной канала в этом случае?
Нет к сожалению, хостер сервера не хочет и не будет ничего менять , собственно сервер не плохой:
Intel Xeon E5345 2.33 (2 processors)
Windows Server 2008 R2 Standard
RAM 8 Gb
Network 1.0Gbps
И потом я же не cisco как я узнаю, кто у меня медленный, кто быстрый ?
Re[4]: Нагруженный TCP сервер как и на чем реализовать
Здравствуйте, AltCtrlDel, Вы писали:
S>>Ясно, я тоже сомтрел на boost но там 60 метров библиотек ... Не суть, для дела не жалко, а как у него с "быстрой" разадчей, то есть если есть куча медленных и куча быстрых клиентов ?
ACD>Ну, асинхронные методы то там есть, конечно. А так, от твоей реализации именно твоей задачи зависит. Если "медленные", застревают и не успевают забирать иногда, так у меня для этого случая специально sqlite прикручена в виде внешнего буфера. Для медленных клиентов смотри размер их mtu, может они вообще через GPRS заходят. Не передавай мелкими порциями, накопи хотя бы до mtu*3, а то много полупустых пакетов летать будет.
То есть накапливать для каждого пользователя (стек пакетов) и при очередном обходе, выгребать столько сколько может принять на данный момент ? А как получить подтверждение что он получил предыдущий пакет ? Хранить MTU каждого и вычислять сколько может принять ? То есть не могу в голове собрать картинку Придется рисовать на бумаге.