23 / 23 / 5
Регистрация: 05.12.2013
Сообщений: 215
|
|
1 | |
Сетевая игра в режиме реального времени. Qt25.10.2014, 19:44. Показов 3166. Ответов 15
Метки нет (Все метки)
Всем привет!
Решил в учебных целях сделать на Qt сетевую игру (для локальной сети) в режиме реального времени. Всё что я знаю о работе с сетью в Qt - глава из книги Макса Шлее. Ну и конечно, в силу своей нубости столкнулся с рядом проблем. А точнее проблема только одна - на "хосте" игра летает, на "клиентах" - лагает. Причин, наверное множество, и вот какие вопросы я хотел бы задать: 1. До того, как я увидел тормоза на "клиенте" я считал, что выделить на клиента 1 порт - это хорошая идея. Сейчас я начинаю задумываться о том, что через 1 порт, наверное, информация идёт туговато. А может я ошибаюсь. Сколько примерно выделяют портов для игр? 2. Таймер запущен только на хосте, для всех клиентов update() происходит по сигналу readyRead() от сервера, после соответствующего чтения информации. Опять же не знаю, хорошая это идея или плохая. Как обычно поступают для координации времени в играх? 3. Все расчеты ведутся только на хосте. Поэтому информации приходится передавать очень много. Это решаемая проблема - каждый клиент может брать на себя часть расчетов и серверу придётся меньше передавать. Однако как же тогда работают настоящие игры, в которых информации передаётся уж явно в разы больше, причем не по локалке, а через интернет, и таких тормозов даже близко нет. Что можете посоветовать по этому поводу? 4. TCP-соединение. Может быть лучше UDP, ибо он быстрее? А что используется в настоящих играх? Тем более, если сделать так, чтобы клиенты сами расчитывали себе часть параметров, а передавались только ключевые, то потеря пакетов становится критичной. Можно, конечно, доработать игру до такой степени, что потери пакетов будут выявляться на стороне клиента и корректироваться с новыми полученными пакетами, но ведь потеря пакетов - это в любом случае плохо? 5. Поскольку учился я по книге М. Шлее, умею подключаться только к конкретному порту конкретного компьютера (по его имени). А как же сделать что-то типа "мониторинга" сети? Вот как, извиняюсь, в варкрафте: Кто-то создал игру - другие видят, что появился такой-то хост, и могут к нему законнектиться. Как происходит сей процесс? Буду благодарен любым советам! Возможно данные вопросы интересны не только мне, и данная тема разовьётся в хорошую дискуссию. Пожалуйста, активно принимаем участие)
0
|
25.10.2014, 19:44 | |
Ответы с готовыми решениями:
15
Работа в режиме реального времени Передача аудио и видео в режиме реального времени Парсер логов в режиме реального времени Отображение данных в режиме реального времени |
187 / 172 / 38
Регистрация: 03.08.2012
Сообщений: 596
|
|
25.10.2014, 22:05 | 2 |
Может быть это и есть основная причина лагов у клиента?
Хотя все зависит от игры, но я считаю, что update стоит делать независимо от того, пришли данные от сервера или нет
0
|
25.10.2014, 23:35 | 3 |
Nelkor, без профилирования все перечисленное полная ерунда. Профилирование
0
|
Почетный модератор
11525 / 4320 / 448
Регистрация: 12.06.2008
Сообщений: 12,410
|
|
26.10.2014, 01:25 | 4 |
Сообщение было отмечено Nelkor как решение
Решение
Эти порты виртуальные и на скорость не влияют. Если для каждого клиента открывать отдельный порт, то прироста производительности не будет. Да и количество клиентов тогда будет ограничено количеством портов.
В TCP надо учитывать то, что это поток данных. Т.е. если отправляются два мелких пакета, то придти они могут в виде одного большого или 10 ещё более мелких. Так же было замечено, что Qt реально отправляет данные только когда начинает выполнять свой основной цикл (при выходе из функций или по qApp->processEvents). Если это не используется, тогда надо проталкивать данные через QTcpSocket::flush(). Возможно, это и приводит к лагам. Я вижу три способа: - использовать общий сервер, который подсказывает, кто создал игру и как к нему подключиться - время от времени сканировать подсеть - время от времени отправлять широковещательный UDP запрос
1
|
23 / 23 / 5
Регистрация: 05.12.2013
Сообщений: 215
|
|
26.10.2014, 14:51 [ТС] | 7 |
Бухгалтер, милый мой бухгалтеееер...
Добавлено через 1 минуту Большое спасибо, Humanoid. Вы не против, если я буду обращаться к Вам впредь по проблемным вопросам, связанным с сетями?)
0
|
23 / 23 / 5
Регистрация: 05.12.2013
Сообщений: 215
|
|
26.10.2014, 14:55 [ТС] | 9 |
И кстати, я правильно понимаю, что широковещательный UDP-запрос, это writeDatagram(..., QHostAdress::Any, ...) ?
Добавлено через 1 минуту Да спасибо, я уже понял, что ты лучше всех знаешь, на что у меня хватит денег, а на что нет. И поосторожнее с оффтопами, а то забанят еще(
0
|
Почетный модератор
11525 / 4320 / 448
Регистрация: 12.06.2008
Сообщений: 12,410
|
|
26.10.2014, 21:31 | 10 |
Скорее QHostAdress::Broadcast - это аналог адреса 255.255.255.255
QHostAdress::Any используется для открытия порта на всех интерфейсах, что является аналогом адреса 0.0.0.0 и это не сработает как широковещательный запрос. Можно даже просто на 255.255.255.255 послать сообщение. Но надо учитывать, что широковещательные пакеты только внутри подсети работают... ближайший роутер их вряд ли выпустит во внешнюю сеть. Т.е. если у вас адрес 192.168.20.5, а маска подсети 255.255.255.0, то этот пакет будет доступен только для адресов 192.168.20.* На форуме принято, что вопросы задаются в соответствующей теме. Так больше шансов получить ответ, т.к. если один не знает ответ, то другие подскажут. К тому же, готовый ответ на вопрос в свободном доступе часто оказывается полезным для других людей, с похожими вопросами. Может, у автора всего 10 активных клиентов, каждый из которых тянет 1 КБ/с по сети и все в сумме грузят процессор на 1% и жрут 10 МБ памяти... и при этом используется навороченный выделенный многопроцессорный Xeon с 256 гигами памяти и 10-гигабитным каналом в интернет. Откуда такие предположения о 1000 активных клиентах и цене VPS'а, если автор об этом ничего не говорил?
0
|
23 / 23 / 5
Регистрация: 05.12.2013
Сообщений: 215
|
|
27.10.2014, 21:38 [ТС] | 11 |
Humanoid, спасибо за советы! Кстати, при получении от сокета сигнала disconnected() реально выцепить его бывший дескриптор? После отсоединения-то он уже равен -1 и не очень то понятно, какой именно клиент отключился. Лично я вижу такое решение - вести QList<qintptr>, в котором хранить все дескрипторы, а при поступления сигнала о дисконекте пробегаться по этому списку и всех проверять (А как проверять? isOpen()? isValid()?) Ну и кто не отзовётся на проверку, того и считать отсоединившимся... Это правильное решение или уже изобретено более круглое колесо?
0
|
23 / 23 / 5
Регистрация: 05.12.2013
Сообщений: 215
|
|
27.10.2014, 22:14 [ТС] | 13 |
В таком случае его дескриптор будет равен -1 Потому что сендером он является уже после дисконнекта
0
|
23 / 23 / 5
Регистрация: 05.12.2013
Сообщений: 215
|
|
28.10.2014, 22:01 [ТС] | 15 |
Я не понимаю, что за тип данных Client*
Добавлено через 3 минуты humanoid, нужна помощь! Я пытаюсь инициализировать сокет таким методом: QTcpSocket *psocket = new QTcpSocket(this); psocket->setSocketDescriptor(descr); descr - это сохранённый дескриптор подключенного сокета. Но сообщение, отправленное как psocket->write(...) не доходит, а в QDebug выводится QSocketNotifier: Multiple socket notifiers for same socket 476 and type Read Как отправлять сообщение какому-то конкретному клиенту? Добавлено через 2 минуты Может быть, вместео дескрипторов вести учет указателей на сокеты присоединившихся клиентов?
0
|
Почетный модератор
11525 / 4320 / 448
Регистрация: 12.06.2008
Сообщений: 12,410
|
|
28.10.2014, 22:41 | 16 |
Я всегда так и делал... получал указатель через QTcpServer::nextPendingConnection()
0
|
28.10.2014, 22:41 | |
28.10.2014, 22:41 | |
Помогаю со студенческими работами здесь
16
Не обрабатывается скрипт в режиме реального времени ОС для работы в режиме реального времени? Выполнение jquery в режиме реального времени Обработка звука в режиме реального времени Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |