Передача объектов на основе поля по сети - PullRequest
3 голосов
/ 04 декабря 2011

Мне нужно передавать объекты .NET (с иерархией) по сети (многопользовательская игра). Чтобы сэкономить пропускную способность, я бы хотел передавать только те поля (и / или свойства), которые меняются, поэтому поля, которые не будут изменены, не будут передаваться.

Мне также нужен какой-то механизм для сопоставления правильных объектов на другой стороне клиента (глобальный идентификатор объекта ... что-то вроде идентификатора объекта?)

Мне нужны предложения, как это сделать.
Вы бы использовали отражение? (производительность критична)
Мне также нужен механизм для передачи дельты IList (добавленные объекты, удаленные объекты).

Как работает MMO-сеть, они передают целые объекты?
(может быть, моя идея передачи по полю глупа)

EDIT:
Чтобы было ясно: у меня уже есть механизм для отслеживания изменений (допустим, у каждого поля есть свойство, сеттер добавляет поле в какой-то список или словарь, содержащий изменения - структура теперь не является окончательной).

Я не знаю, как сериализовать этот список, а затем десериализовать его на другом клиенте. И в основном, как это сделать эффективно и как правильно обновлять объекты.

Там около ста объектов, поэтому я стараюсь избегать ситуаций, когда я бы написал специальную функцию для каждого объекта. Было бы неплохо украшать поля или свойства атрибутами (например, указать сериализатор, идентификатор поля или что-то подобное).

Подробнее об объектах: каждый объект имеет в среднем 5 полей. Некоторые объекты наследуются от других.

Спасибо за все ответы.

Ответы [ 5 ]

2 голосов
/ 05 декабря 2011

Я просто скажу заранее, что предложение Марка Гравелла действительно правильный подход. Он замалчивает некоторые второстепенные детали, такие как разрешение конфликтов (вы можете прочитать о работе Лесли Лэмпорта. Он посвятил всю свою карьеру описанию различных подходов к решению конфликтов в распределенных системах), но идея это звук.

Если вы хотите передать моментальные снимки состояния вместо процедурных описаний изменений состояния, тогда я предлагаю вам взглянуть на создание различий снимков в виде префиксных деревьев. Основная идея заключается в том, что вы строите иерархию объектов и полей. Когда вы изменяете группу полей, любой их общий префикс включается только один раз. Это может выглядеть так:

world -> player 1 -> lives: 1
...               -> points: 1337
...               -> location -> X: 100
...                           -> Y: 32
...   -> player 2 -> lives: 3

(все в «...» передается только один раз).

2 голосов
/ 04 декабря 2011

Самый дешевый способ отследить грязные поля - это использовать его в качестве ключевой функции вашей объектной модели, то есть с полем "fooDirty" для каждого поля данных "foo", которое вы устанавливаете в true в "наборе" (еслизначение отличается).Это также может быть объединено с условной сериализацией, возможно, паттерном «ShouldSerializeFoo ()», наблюдаемым несколькими сериализаторами.Мне неизвестны какие-либо библиотеки, которые соответствуют точно тому, что вы описываете (если только мы не включаем DataTable, но ... подумайте о котятах!)

Возможно, еще одна проблема заключается в необходимости отслеживатьвсе объекты для слияния при десериализации;это само по себе не бесплатно.

Однако, учитывая все обстоятельства, я думаю, что вы могли бы сделать что-то по приведенным выше строкам (fooDirty / ShouldSerializeFoo) и использовать protobuf-net в качестве сериализатора, потому что (что важно)который поддерживает как условную сериализацию, так и слияние.Я бы также предложил интерфейс, такой как:

ISomeName {
    int Key {get;}
    bool IsDirty {get;}
}

IsDrty позволит вам быстро проверить все ваши объекты на предмет изменений, затем добавить ключ в поток, а затем (условную) сериализацию.Вызывающая сторона считывает ключ, получает необходимый объект (или выделяет новый с этим ключом), а затем использует десериализацию с поддержкой слияния (передавая существующий / новый объект).

Не полная прогулкачерез, но , если бы это был я , это подход, на который я бы смотрел.Примечание: добавление / удаление / упорядочение объектов в дочерних коллекциях - сложная область, о которой, возможно, стоит подумать.

2 голосов
/ 04 декабря 2011

другой подход; не пытайтесь сериализовать сложные изменения данных: вместо этого отправьте только действительные команды для применения (в краткой форме), например:

move 12432 134, 146
remove 25727

(который переместит один объект и удалит другой).

Затем вы примените команды на приемнике, что позволит выполнить полную повторную синхронизацию, если они не синхронизированы.

Я не предлагаю, чтобы вы на самом деле использовали для этого текст - это просто, чтобы сделать пример более понятным.

Одна приятная вещь об этом: он также предоставляет функцию «воспроизведения» бесплатно.

1 голос
/ 04 декабря 2011

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

Если вы все равно решите попробовать это, я бы попытался сопоставить ваши объекты сDataSet и использовать его встроенные механизмы отслеживания изменений.

Я все же думаю, что вы должны сделать это вручную.

1 голос
/ 04 декабря 2011

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

Мое предлагаемое решение для вас - разложить ваши объекты до минимума и быстро отправить эти маленькие объекты. Кроме того, вы можете использовать сжатие для уменьшения использования полосы пропускания.

Для идентификатора объекта вы можете использовать статический идентификатор, который увеличивается при создании нового объекта.

Надеюсь, этот ответ поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...