Модераторы: feodorv
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> [BCB2009] Многопоточночть. Online игра. Синхронизация. Пул потоков/Pool threads 
:(
    Опции темы
MuForum
Дата 9.8.2009, 18:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 427
Регистрация: 13.6.2007
Где: Молдова, Кишинев

Репутация: нет
Всего: 4



Доброе время суток.
Работаю на "Borland C++ Builder 2009".
Мне необходимо написать программу на подобие прокси-сервера для Online игры. (MMORPG)
Необходимо создавать для одного пользователя два потока:
1. Клиент <> моя программа
2. моя программа <> Сервер
Программа должна поддерживать ~1000 пользователей. То есть, это 2000 потоков + 1 прослушивающий(Listen) = Итого ~2001 потоков.
Работаю я с асинхронными функциями передачи данных: WSA*()

После многодневного чтения форумов я понял, что для моей задачи мне необходимо организовать пул потоков/Pool threads.
- Так же я понял, что кол-во поток в пуле должен быть: кол-во процессоров + 1, а не так как писал Рихтер, что кол-во процессоров * 2.

Собственно система передачи данных между клиентами у меня уже реализована и работает на ура.
- Почему я создал данную тему?
- Потому, что раньше кол-во игроков не достигало больше 120 пользователей, а как только это число резко выросло, я столкнулся с тем, что по достижению какого-то кол-во пользователей, новый пользователи подключится не могут, а старые продолжают играть. Во время подключения в таком случае пользователей получает ошибку номер 10053 (WSAGetLastError()).

Во время чтения статей про многопоточность я познакомился с понятиями "переключение между потоками" и его негативном влияние на скорость обработки данных.

Прочитал статью на RSDN: Эффективная многопоточность;
Прочитал статью "Джеффри РИХТЕР "Windows для профессионалов"": Глава 11. Пулы потоков;
- Многое прояснилось. Какую-то часть даже понял =)

В общем меня заинтересовала реализации через: "Встроенная поддержка пула потоков". ( QueueUserWorkItem() )
- Только вот как применить эту функцию на практике не могу понять. Искал в гугле примеры, но кроме частных особо нечего и не встретишь.


P.S. -> Прошу помощи в реализации. То есть, может кто-то подкинет название какой-то книги, либо примерчик(нормальный). 

Это сообщение отредактировал(а) MuForum - 9.8.2009, 18:58


--------------------
"Чтобы правильно задать вопрос, нужно знать большую часть ответа!" (Р. Шекли)
PM MAIL WWW ICQ Skype MSN   Вверх
Romikgy
Дата 9.8.2009, 18:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Любитель-программер
****


Профиль
Группа: Участник Клуба
Сообщений: 7326
Регистрация: 11.5.2005
Где: Porto Franco Odes sa

Репутация: нет
Всего: 146



Цитата(MuForum @  9.8.2009,  17:26 Найти цитируемый пост)
Borland C++ Builder 2009

используя это я бы восплользовался Indy там есть уже прокси ....


--------------------
Владение русской орфографией это как владение кунг-фу — истинные мастера не применяют его без надобности. 
smile

PM   Вверх
MuForum
Дата 9.8.2009, 18:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 427
Регистрация: 13.6.2007
Где: Молдова, Кишинев

Репутация: нет
Всего: 4



Цитата(Romikgy @ 9.8.2009,  18:35)
Цитата(MuForum @  9.8.2009,  17:26 Найти цитируемый пост)
Borland C++ Builder 2009

используя это я бы восплользовался Indy там есть уже прокси ....

Мне необходимо немного другое ежели прокси-сервер, но по своей сути тоже самое.
Мне необходимо написать спец.программу, которая будет пропускать через себя все игровые пакеты пользователей и проверять нужные аспекты, чтобы игроки не прибегали к некоторым "чудесам" игры.
У меня встала задача реализовать пул потоков. Столкнулся я с этим в первые, поэтому пока как реализовать понимаю только в общих чертах. Перед созданием тему я несколько дней читал статьи по данной теме, чтобы иметь представление о том, чего мне нужно добиться.
То есть, мне нужно создать пул потоков, чтобы потоки от пользователей вставали в очередь для обработки.


# Добавлено: Когда подключается новый пользователь, я инициализирую класс "CS_Item", и помещаю его в список.
Код

class CS_Item
{
    public:
        unsigned long ID; // Идентификатор пользователя;
        TS_CS *cs; // Класс для обмена данными между Клиентом и моей программой;
        TS_SG *sg; // Класс для обмена данными между Сервером и моей программой;
};

Далее я инициализирую класс "TS_CS" для обмена данными с клиентом.
Код

class TS_CS: public TThread
{
    private:
        SOCKET sListen; // Сокет клиента;
        SOCKET sSocket; // Сокет сервера;
        AnsiString sIPAddress;
        unsigned long sID;
        ....
    public:
        __fastcall TS_CS::TS_CS(bool CreateSuspended): TThread(CreateSuspended) {};
        virtual void __fastcall Execute(void);
        ...
};

После того, как пользователь заходит в игру и выбирает сервер на котором он хочет играть, я инициализирую класс "TS_SG" для обмена данными с сервером.
Код

class TS_SG: public TThread
{
    private:
        SOCKET sListen; // Сокет сервера;
        SOCKET sSocket; // Сокет клиента;
        AnsiString sIPAddress;
        unsigned short sPort;
        unsigned long sID;
        ...
    public:
        __fastcall TS_SG::TS_SG(bool CreateSuspended): TThread(CreateSuspended) {};
        virtual void __fastcall Execute(void);
        ...
};

Далее уже происходит обмен данными между клиентом и сервером через мою программу, через эти два потока.


P.S. -> Надеюсь изъяснился доступно.

Это сообщение отредактировал(а) MuForum - 9.8.2009, 18:51


--------------------
"Чтобы правильно задать вопрос, нужно знать большую часть ответа!" (Р. Шекли)
PM MAIL WWW ICQ Skype MSN   Вверх
Romikgy
Дата 9.8.2009, 21:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Любитель-программер
****


Профиль
Группа: Участник Клуба
Сообщений: 7326
Регистрация: 11.5.2005
Где: Porto Franco Odes sa

Репутация: нет
Всего: 146



Цитата(MuForum @  9.8.2009,  17:40 Найти цитируемый пост)
Мне необходимо немного другое ежели прокси-сервер

точнее ...

 и где вопросы ?



--------------------
Владение русской орфографией это как владение кунг-фу — истинные мастера не применяют его без надобности. 
smile

PM   Вверх
Alca
Дата 9.8.2009, 21:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3993
Регистрация: 14.6.2006

Репутация: 1
Всего: 50



Цитата

используя это я бы восплользовался Indy там есть уже прокси ....

Там еще есть такое IdSchedulerOfThreadDefault (Indy 10).
Сразу скажу, что не юзал этот компонент.  smile 

Это сообщение отредактировал(а) Alca - 9.8.2009, 21:35


--------------------
PM WWW ICQ Skype Jabber   Вверх
Lazin
Дата 9.8.2009, 22:04 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 5
Всего: 154



Цитата(MuForum @  9.8.2009,  18:26 Найти цитируемый пост)
QueueUserWorkItem

лучше использовать порты завершения
PM MAIL Skype GTalk   Вверх
SVN74
Дата 9.8.2009, 22:17 (ссылка)    | (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 740
Регистрация: 5.5.2008
Где: Комсомольск на Дн епре

Репутация: 1
Всего: 18



Я с такой штучкой сталкивался, - правда у меня было на блокирующих сокетах и применял я CreateThread, - тоже при большом количестве народу отсекало некоторых...
Дело было: accept - > CreateThread, - когда accept передавал в поток (КОПИЮ) сокета, то проходит определенное время создания нового потока, а accept продолжает работать получая новый сокет... Получается - пока создастся новый поток, то копия сокета до него не доходит.
Я просто поставил задержку между созданием нового потока и созданием очередного сокета и все.... smile

PM MAIL WWW   Вверх
Lazin
Дата 9.8.2009, 22:34 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 5
Всего: 154



SVN74, порождать поток для каждого нового клиента - некошерно
PM MAIL Skype GTalk   Вверх
SVN74
Дата 9.8.2009, 22:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 740
Регистрация: 5.5.2008
Где: Комсомольск на Дн епре

Репутация: 1
Всего: 18



Цитата(Lazin @  9.8.2009,  22:34 Найти цитируемый пост)
порождать поток для каждого нового клиента - некошерно 

Оно то так, если стоит стандартная задача для всех клиентов, а если задач много типа ftp, gsm,video и тд.?
PM MAIL WWW   Вверх
Lazin
Дата 10.8.2009, 08:09 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

Репутация: 5
Всего: 154



Цитата(SVN74 @  9.8.2009,  22:40 Найти цитируемый пост)
Оно то так, если стоит стандартная задача для всех клиентов, а если задач много типа ftp, gsm,video и тд.?

это не важно, механизм IOCP, позволяет организовать диспетчеризацию разных событий

если вкратце, то выглядит оно так: ты создаешь порт завершения, связываешь объекты(файлы, сокеты) с ним, с каждым объектом(клиентом) может быть связан еще один объект(completion key), когда ты начинаешь операцию на сокете, она выполняется асинхронно(send/recv возвращают управление сразу, не дожидаясь, когда произойдет ввод/вывод) и с ней можно связать структуру OVERLAPPED(конечно это может быть не эта структура, а к примеру ее наследник, содержащий дополнительные поля). Дальше, когда операция завершается, ты можешь вызвать ф-ю GetQueuedCompletionStatus, и получить ключ завершения(completion key) и структуру OVERLAPPED(или то, что ты передал вместо нее), завершенной асинхронной операции. Эти данные однозначно идентифицируют клиента твоего сервера а так-же конкретную операцию ввода-вывода, которая завершилась для данного клиента.
Типичный пример использования - ты создаешь М потоков, и в каждом из низ выполняется цикл, в котором вызывается ф-я GetQueuedCompletionStatus, это похоже на обработку сообщений windows, только в несколько потоков. 
Порт завершения можно настроить так, что-бы на нем могли выполняться одновременно только К потоков(К < M). К примеру, у тебя в пулле потоков - 20 потоков, а на порте завершения может работать только 10 потоков одновременно. Допустим в начальный момент времени, все потоки в режиме ожидания (сидят в ф-ии GetQueuedCompletionStatus). После того, как на порте завершения произойдет какое-либо событие, у тебя в одном из потоков, ф-я GetQueuedCompletionStatus, вернет управление, после чего твой код обработает это событие и снова вызовет эту ф-ю и будет ждать следующего события. Если произойдет 10 событий, то у тебя будут работать все 10 потоков. Если в этот момент произойдет 11-е событие, оно будет помещено в очередь, до тех пор, пока один из 10 работающих потоков не перейдет в состояние ожидания, к примеру вызвав ф-ю GetqueuedcompletionStatus. Но в состояние ожидания поток может перейти, вызвав к примеру ф-ю WrteFile(синхронно), либо WaitForSingleObject. В общем, если один из 10 работающих потоков по какой-либо причине должен будет что-нибудь ждать, то система разбудит еще один поток из пулла, и передаст туда 11-е событие. В результате, даже если у тебя в коде обработчиков событий есть синхронный ввод/вывод, или ожидание всяких локов, процессор простаивать не будет.
В общем, механизм очень эффективен, для реализации высоко-нагруженного сервера лучше использовать именно его.
Статья Русиновича - Inside IOCP

Это сообщение отредактировал(а) Lazin - 10.8.2009, 08:11
PM MAIL Skype GTalk   Вверх
Alca
Дата 10.8.2009, 12:28 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3993
Регистрация: 14.6.2006

Репутация: 1
Всего: 50





--------------------
PM WWW ICQ Skype Jabber   Вверх
Alca
Дата 10.8.2009, 12:56 (ссылка) |    (голосов:3) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3993
Регистрация: 14.6.2006

Репутация: 1
Всего: 50





--------------------
PM WWW ICQ Skype Jabber   Вверх
MuForum
Дата 10.8.2009, 14:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 427
Регистрация: 13.6.2007
Где: Молдова, Кишинев

Репутация: нет
Всего: 4




Модератор: Сообщение скрыто.



--------------------
"Чтобы правильно задать вопрос, нужно знать большую часть ответа!" (Р. Шекли)
PM MAIL WWW ICQ Skype MSN   Вверх
MuForum
Дата 14.8.2009, 01:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 427
Регистрация: 13.6.2007
Где: Молдова, Кишинев

Репутация: нет
Всего: 4



# for all - Нашел небольшую статью про "Порты завершения": Модель порта завершения;
- Может кому-то пригодится.


--------------------
"Чтобы правильно задать вопрос, нужно знать большую часть ответа!" (Р. Шекли)
PM MAIL WWW ICQ Skype MSN   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Сети | Следующая тема »


 




[ Время генерации скрипта: 0.0603 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.