|
|
Регистрация Восстановить пароль |
Регистрация | Задать вопрос |
Заплачу за решение |
Новые сообщения |
Сообщения за день |
Расширенный поиск |
Правила |
Всё прочитано |
|
Опции темы | Поиск в этой теме |
26.07.2009, 19:47 | #1 |
Инженер ИС
Старожил
Регистрация: 13.12.2006
Сообщений: 2,671
|
Сеть в игре (MMO 2D RPG)
Братцы, выручайте! ...очень прошу.
Дело такое. Вот я написал сокетное соединение, игроки подключаются/отключаются, все работает, но! ...известно, что TServerSocket при уходе одного из каналов переназначает список Connection. Стало быть, мой массив с записями игроков хранит теперь неверные идентификаторы каналов, ведь сокет переписал свой список каналов "не сообщив" массиву как он его изменил. Наступает такая ситуация, когда пробежав по массиву записей пользователей сервер пытается отправить данные конкретному по устаревшему номеру канала, которого может уже не существовать, или отправляет их не в тот канал. Когда игрок был один все было нормально, ...два - тоже, но когда игроков (кроме ботов) поболее, то возникает путаница или вылетают ошибки. Есть ли какие-нибудь решения по этому поводу? ...а то башня уже закипает. По идее нужно заставить сервер одновременно со своим обновлением списка каналов, обновить и записи массива, указав правильные номера каналов, на основании прежнего списка и нового. Буду весьма благодарен за советы, идеи, ссылки на инфу и пр.
Руководитель проекта MMO 2D RPG: Настоящее имя Денис Стрижак (10.05.1981-6.02.2019) Мир духу его
|
27.07.2009, 00:56 | #2 |
Eclipse Foundation
Старожил
Регистрация: 19.09.2007
Сообщений: 2,604
|
Попробуйте сделать соответствие между списком каналов сервеного сокета, и массивом клиентов. Можно ввести дополнительный массив, который будет служить флагом для каждого канала, то есть типа канал изменен - флаг по данному индексу в массиве флагом установлен в true или в 1. То есть нужно проверить соедниение. А если флаг не установлен (false или 0) проверять соединение не нужно.
Или второй способ - сделать все "на лету", то есть после каждого отключения клиента - вызывать функцию, которая будет проверять все соединения - ну например отправлять какой-то маленький тестовый пакет, по TCP протоколу(ну чтобы с подтверждением доставки было), и сразу менять ситуацию в массиве клиентов, с которыми должен работать сервер. Но в обоих случаях нужно вести четкое соответствие списку каналов массива клиентов. Этим можно решить еще одну проблему - два игрока с одного IP, просто проверять на наличие клиента с таким IP в списке и если есть - банить или высылать предпреждение о том, что кто-то хочет выйти с таким же IP в игру. |
27.07.2009, 14:56 | #3 |
Инженер ИС
Старожил
Регистрация: 13.12.2006
Сообщений: 2,671
|
С двумя игроками с одного IP все уже сделано, более того, сервер различает каждую машину, например из под сети с одним IP.
На счет "опроса каналов", т.е. отослать пакет и ждать ответ, после чего подправить номер в массиве - это метод довольно варварский, нагружает сервер ненужными пересылками. В чате так можно, ...у меня (по статье) после изменения числа каналов идет опрос всех пользователей, и составление списка идет заново. В игровом сервере - это непозволительная роскошь. Представьте себе, в секунду подключается и отключается например 100 человек, у всех для идентификации какой-то пакет, ничто не мешает положить сервер на этом деле, это дыра просто, ...в худшем случае сервер будет заниматься переназначением записей в массиве а не самой игрой )) Дело в чем? ...мы не ждем, что пользователь выйдет корректно, т.е. как можно было бы с клиента отсылать пакет "я ушел" и этим самым определять, какой канал сейчас нужно искусственно закрыть. Тут все четко. Но, ...во-первых это тоже дыра в системе, во-вторых при сбое в сети или закрытии приложения перезапуском компа сервер будет считать, что пользователь в игре, номер его канала так же будет считаться в массиве рабочим, пока он не вызовется и сервер не выдаст ошибку "out of list". Но, минуточку, ...сокет не показывает номер отпавшего канала, он тихо создает новый список, сдвигая все числа к первым, т.е. если были каналы: 1,2,3,4,5,6,7 и вылетел 4-й, то список станет: 1,2,3,4,5,6 причем 4-й это бывший 5-й и т.д. Именно это и беспокоит, ...даже если организовать сравнение, все равно не удасться узнать номер отпавшего канала, ...а если этот способ есть, то достаточно пробежаться по массиву записей, найти отпавший номер, пометить запись как не используемую, а все последующие идентификаторы каналов заменить на "тот что записан минус 1". Вот такие вот пироги. Помогите пожалуйста найти метод извлечения номера отпавшего канала, и все будет решено. Послесловие: ...да, чуть не забыл, ...если использовать для идентификации IP-адрес пользователя, то мы отсекаем "подсетчиков", домашние сети, клубы, интернет-кафе и пр. ...только одна машина с одного интернет-IP-адреса.
Руководитель проекта MMO 2D RPG: Настоящее имя Денис Стрижак (10.05.1981-6.02.2019) Мир духу его
Последний раз редактировалось Beermonza; 27.07.2009 в 15:04. |
27.07.2009, 15:12 | #4 | |
Eclipse Foundation
Старожил
Регистрация: 19.09.2007
Сообщений: 2,604
|
Цитата:
Можно попробовать написать свой класс, наследованный от TServerSocket, и самому контроллировать управление списком каналов. Но это влечет за собой необходимость переписывать основные функции исходного класса. Но лучше сделать вот как. Просто поставить проверку на наличие соединения перед отправкой очередного пакета клиенту. Если клиент отрубился некорректно, вылетит исключение - ловите его, и в обработке исключения помечаете этот канал как неиспользуемый. В данном случае важно поймать исключение, а то оно положит весь сервер. На С++ это делается блоком Код:
Но, кстати, вам всеравно понадобится проверять весь список, потому что отключится могут сразу несколько. Например было 1,2,3,4,5,6,7,8 отключились 2,5,7 вам нужно сдвинуть 3 и 4 на одну позицию, 6 на две, а 8 на 3 Последний раз редактировалось MaTBeu; 27.07.2009 в 15:19. |
|
27.07.2009, 16:37 | #5 |
Инженер ИС
Старожил
Регистрация: 13.12.2006
Сообщений: 2,671
|
Хорошо, буду проверять, ...отлов исключений получше будет ожидания пакетов, или что-то в этом роде.
Руководитель проекта MMO 2D RPG: Настоящее имя Денис Стрижак (10.05.1981-6.02.2019) Мир духу его
|
27.07.2009, 16:58 | #6 | |
Инженер ИС
Старожил
Регистрация: 13.12.2006
Сообщений: 2,671
|
Вот что было предложено.
Цитата:
Руководитель проекта MMO 2D RPG: Настоящее имя Денис Стрижак (10.05.1981-6.02.2019) Мир духу его
|
|
27.07.2009, 23:36 | #7 |
Инженер ИС
Старожил
Регистрация: 13.12.2006
Сообщений: 2,671
|
Как синхронизировать сокет с записями в массиве
Значит так. Выбрал я пример alexBlack'a и пристроил в свой протокол. Работает без сбоев.
Принцип У меня все персонажи числятся в одном массиве записей UnitsMas, собственного типа TGUnits. В нем есть некая запись типа Word - UChannel. Когда идет подключение и опрос пользователя этой переменной присваивается порядковый номер в массиве, который система выдала ему: Код:
Код:
Код:
Спасибо всем за советы.
Руководитель проекта MMO 2D RPG: Настоящее имя Денис Стрижак (10.05.1981-6.02.2019) Мир духу его
|
Похожие темы | ||||
Тема | Автор | Раздел | Ответов | Последнее сообщение |
Как сделать сеть в простенькой игре??? | Руслантус | Gamedev - cоздание игр: Unity, OpenGL, DirectX | 16 | 21.05.2010 20:44 |
RPG на Дельфи | Juffin | Gamedev - cоздание игр: Unity, OpenGL, DirectX | 10 | 10.04.2009 21:37 |
Создание текстового RPG | KORN | Софт | 3 | 15.07.2008 09:21 |
3D-RPG | Кронос | Gamedev - cоздание игр: Unity, OpenGL, DirectX | 25 | 12.05.2007 11:21 |