| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Сети > Нужна помощь |
| Автор: vikaz 16.12.2008, 09:41 |
| Всем добрый день! Передо мной поставили задачу написать клиент-серверное приложение, обменивающиеся данными через интернет. Есть клиентское приложение, которое отправляет на сервер текстовые сообщения, являющиеся по сути командами, а также графику (bmp, jpg, gif). Сервер получает данную строку и формирует из нее SQL запрос, данный запрос отправляется базе MySQL, которая отрабатывает данный запрос и возвращает данные, которые переправляются обратно клиенту. Клиент их визуализирует. Примерное количество клиентов, которые будут подключаться к серверу равно 1000 (это примерно). Пишу на с++ Builder 2009. Сначала я думал писать при помощи Indy, но ребята меня переубедили, что этого не стоит делать, а лучше написать транспортный модуль самому. Под транспортным модулем я подразумеваю не новый протокол обмена данными по сети, а так сказать интерфейс работающий с TCP/IP протоколом. Почитав литературу и порывшись на сайтах, нашел много информации и методов работы с TCP/IP, НО НА КАКОМ ОСТАНОВИТЬСЯ не знаю. Поэтому и прошу у Вас помощи. Вот основные методы для работы с TCP/IP протоколом: 1. Блокирующий(синхронный) сокет. 2. Не блокирующий (асинхронный) сокет. Для нормальной работы первого метода, создаются потоки, при подключении нового клиента к серверу. Как мне кажется плюс этого метода, что одна на писаная функция работы с клиентом и каждый раз запускаемая в потоке решает все задачи, которые я пропишу. Но вопрос, не накладно ли будет для железа создавать 1000 потоков, разгребет ли, и есть ли смысл и целесообразно ли? Но есть и большой минус. Допустим, что был вызов функции recv, но по каким-то причинам она не вернула данные. В этом случае она останется заблокированной навечно, и сервер больше не будет реагировать на действия пользователя. Второй метод более гибкий, но он и труднее в программировании и лишен выше описанной проблемы. Для асинхронных соке тов так же можно выделить несколько методов: 1. Использование массива соке тов и с использованием select 2. Использование соке тов через события windows 3. Асинхронная работа через объекты событий. Описывать +/- каждого метода долго. Но вся проблема, для меня, упирается в то, как использовать асинхронные сокеты 2 и 3 для 1000 подключенных, как отслеживать, от кого пришла стока и кому ответить (для всех трех методов). И ко всему этому остается проблема правильности доставки сообщений, не факт, и это известно, что данные придут сразу все. Могут придти не все, а если сообщения маленькие, то они могут придти сразу оба. Как при использовании асинхронного сокета учесть это и при синхронном тоже? Надеюсь не утомил. Очень нужна помощь, направьте на путь истинный! Заранее спасибо. |
| Автор: J0ker 17.12.2008, 05:16 |
| не изобретайте велосипед используете паттерн реактор кол-во потоков = кол-во ядер * 2 для винды используете completion ports, для *nix - пулы - если есть, select - если пулов нет - оптимально можно заюзать boost::asio - там использование этих фич скрыто в классах |
| Автор: vikaz 17.12.2008, 07:19 |
| J0ker, можно подробнее. Много "красивых" слов. Но пока они мне не все понятны. |
| Автор: Cтpaнник 17.12.2008, 10:07 |
| http://www.codeproject.com/info/search.aspx?artkw=IOCP+server |
| Автор: vikaz 17.12.2008, 12:41 |
| Cтpaнник, не могу с этого сайта ничего скачать. Можешь скинуть скаченные архивы, благо они весят не много. + ссылочку на описание IOCP. не могу найти русскоязычного описания! Заранее спасибо! |
| Автор: Олег2005 17.12.2008, 15:27 |
| Тут найдете основное: |
| Автор: Cтpaнник 17.12.2008, 16:19 |
| vikaz, там чтобы что-то скачивать (архивы, примеры и т.п.) просто надо зарегистрироваться. Это бесплатно |
| Автор: J0ker 17.12.2008, 17:05 | ||
паттерн многопоточный реактор - создаете пул потоков которые сидят на ожидании (лучше организовать LIFO) в случае пулов и completion ports - когда приходит сообщение первый свободный поток из очереди его подхватывает и вызывает соответствующий обработчик в случае использования select - диспетчер подхватывает сообщение, и соответственно типу передает его потоку инициализированному конкретным обработчиком по поводу кол-ва потоков в пуле обычно бессмысленно держать в работе больше потоков, чем имеется ядер но учитывая особенности например completion ports, надо иметь под рукой запасные потоки, т.к. при попадании работающего потока в операцию, вызывающую какую-либо wait функцию, система считает, что можно запустить еще один поток. т.о. все зависит от того, что делает обработчик - если это голые вычисления, допустим, где гарантированно нет wait вызовов, то можно ограничится кол-вом потоков равным кол-ву ядер, если-же есть обращение, например, к удаленной базе данных с длительными ожиданиями - то здесь нужно увеличить кол-во потоков в пуле больше чем 2*кол-во ядер можно попробовать сделать динамический пул - если запущеный поток последний в пуле, то создается еще один - т.е. пул никогда не бывает пустым, если-же поток не запускался определенное время, то он уничтожается - по идее для LIFO эта тактика должна быть довольно эффективна... ЗЫЖ да, и посмотрите все-таки boost::asio - возможно это как раз то, что вам нужно |
| Автор: vikaz 18.12.2008, 11:28 |
| Ребята, всем огромное спасибо, буду смотреть и разбираться. Олег2005 и тебе спасибо за файл. |
| Автор: vikaz 18.12.2008, 12:07 |
| Олег2005, это вырезка, а откуда? Если не секрет..... |
| Автор: Олег2005 18.12.2008, 12:11 |
| Это из моего учебника по сетевому программированию |
| Автор: MAKCim 18.12.2008, 13:25 |
| http://forum.vingrad.ru/forum/topic-238484/kw-select-fork.html |
| Автор: vikaz 18.12.2008, 14:01 |
| MAKCim спс, за ссылку. Олег2005 и много у тебя там такого интересного? Можно ли как-то её почитать? |
| Автор: vikaz 19.12.2008, 08:52 | ||||
| Олег2005, спасибо еще раз за инфу. Но у меня по ней возникли вопросы. А именно к серверной части, так как в клиентской все просто. Вопросы: 1. В фунции main в конце есть сл. код:
Сам вопрос, зачем в конце сл. строки?
Что ты пытаешься тут отправить. Как мне показалось, ты просто ошибся и я убрал эти строки. Но Код так и не заработал. Точнее часть. Сервер показывает, что клиент подключился, но сообщения не принимает и не отправляет! :( еще возник вопрос, в структуре мы не вводили данный параметр, но он присутствует: op->hEvent = 0; |
| Автор: Олег2005 19.12.2008, 15:24 | ||
| Посмотрите вот http://www.gamedev.ru/community/mmorpg/forum/?id=68129 Там есть кое-какие комментарии.
Да нет, там не отправка - а прием от клиента - WSARecv Это поле из структуры OVERLAPPED, которая включена в структуру ovpConnection, и его имя - hEvent - по умолчанию. И еще - в функцию void SendToAll(char *buffer,unsigned long bytes) тоже надо добавить op->hEvent = 0; |
| Автор: vikaz 19.12.2008, 15:26 |
| Спасибо, гляну на выходных. Там будет видно! |
| Автор: vikaz 22.12.2008, 07:39 | ||||
| Всем привет! Посмотрел я статью, не очень много полезной информации я там нашел ДЛЯ СЕБЯ. Возникли вопросы и опять же по серверной части: - Как мы уже выяснили в конце функции main есть строка принимающее сообщение, но я так и не нашел строки, которая отправляет полученное сообщение клиенту. Зато нашел еще одну функцию для приема, это так и нужно или......?
Вопрос собственно вот в этом месте:
И еще, я так и не въехал, про 4 байта, где они там у тебя передаются. Это все про то, что передается только одно сообщение от клиента И что еще интересного. Моя антивирусная программа, определяет код сервера как вирус. |