PDA

Просмотр полной версии : Интерфейс передачи данных: сервер -> флэш


litebox
26.05.2010, 19:18
Доброго времени суток.
В ходе разработки он-лайн игры и разработки общения клиент-сервер (с помощью xml, описывающей экземпляры объектов (классов)) появился такой вопрос: должен ли разработчик клиента жертвовать удобством и быстродействием в угоду удобства и быстродействия серверу, и в какой степени. Интересно ваше мнение.

Думаю, почти все скажут, что да, сервер важнее, поэтому приведу конкретный пример: сервер, написанный на си-шарпе, выбирает данные из базы данных, формирует свои классы и делает серриализацию в xml. На выходе получается что-то типа:
<object>
<properties>
<property name="posX" value="10"/>
<property name="posY" value="20"/>
<property name="name" value="vasya"/>
</properties>
</object>
Так вот, парсить такое добро не очень удобно, так-как приходиться делать цикл for each, перебирающий все узлы properties, в котором реализован switch, определяющий, что если имя равно posX, то мы присваиваем координату объекта, если имя равно name, то присваиваем имя и т.д.
Я сколняюсь к варианту:
<object>
<properties posX="10" posY="20" name="vasya">
</properties>
</object>
таким образом проще получить доступ к этим данным:

pos.x = String(data.@posX);
pos.y = String(data.@posY);
name = String(data.@name);

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

Какие есть соображения по этому поводу, и как можно облегчить флэшу доступ к свойствам объекта, если все же оставить первый вариант передачи данных?

mooncar
26.05.2010, 19:38
Вопрос небольшой - а зачем вам вообще нужен XML в данном случае? Получается, что сперва сервер у вас "выбирает данные из базы данных", формирует XML, а потом этот XML надо еще парсить, то есть теперь уже разбирать.
Может быть я что-то не понимаю? Разве нельзя данные сразу клиенту отдавать?

Котяра
26.05.2010, 21:13
а может компромисс?
<object>
<properties>
<posX value="10"/>
<posY value="20"/>
<name value="vasya"/>
</properties>
</object>
или тогда:
<object posX="10" posY="20" name="vasya"/>

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

mikhailk
27.05.2010, 00:05
+1 )))
темнит серверный программер
либо лень 20 строчек кода подправить, либо написано так, что он боится это трогать

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

но это не рассматриваемый случай

litebox
27.05.2010, 13:18
Вопрос небольшой - а зачем вам вообще нужен XML в данном случае? Получается, что сперва сервер у вас "выбирает данные из базы данных", формирует XML, а потом этот XML надо еще парсить, то есть теперь уже разбирать.
Может быть я что-то не понимаю? Разве нельзя данные сразу клиенту отдавать?
Ну, нам же нужно в каком-то виде передавать данные: простой GET-строкой, в виде xml или JSON, либо бинарные данные по сокету... В нашей реализации вся динамика передается по сокету, а статика - инициализация игровых объектов и собственно игрового уровня на их основе - одним POST-запросом, в виде xml-дерева.

а может компромисс?
<object>
<properties>
<posX value="10"/>
<posY value="20"/>
<name value="vasya"/>
</properties>
</object>
или тогда:
<object posX="10" posY="20" name="vasya"/>

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

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

mikhailk
27.05.2010, 14:50
Вас дурят. ))

Вот здесь на пальцах расписана сериализация на дот.нет'е
http://www.realcoding.net/articles/xml-serializatsiya-v-net-framework-20-tips-tricks.html

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

Котяра
27.05.2010, 14:51
http://www.realcoding.net/articles/xml-serializatsiya-v-net-framework-20-tips-tricks.html
2 вида сериализации:
<DataClass >
<Name>Just Name</Name>
</DataClass>

и

<Data Name="Just Name"/>

UPD: блин.. опередили)
одним гуглом пользовались)

mikhailk
27.05.2010, 15:02
)))))))
я пользовался "негуглом", но сути это не меняет ))

litebox
27.05.2010, 16:31
За ссылку по серриализации спасибо - врага нужно знать в лицо ))))
Я, пожалуй, не совсем верно выразился:
дело в том, что элемент
<properties>
<property name="posX" value="10"/>
<property name="posY" value="20"/>
<property name="name" value="vasya"/>
</properties>
получается в следствии того, что это серриализованный массив, т.е. на стороне сервера политика такая: база данных должна масштабироваться "вдоль и поперек", все свойства объектов - могут быть в любой момент добавлены или, наоборот, удалены, поэтому серверный класс-обертка, который получает данные из базы, без разбору набивает ими массив properties, и отдает их серриализованный вариант флэш-клиенту. С моей же стороны, конкретный объект обладает вполне конкретными свойствами, которые я ожидаю получить, т.е. если это "ОсновнойОбъектМира" - я должен получить его ширину, высоту и т.д., если это "Персонаж" - в добавок к ширине и высоте мне нужен список его анимаций и т.д.

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

mikhailk
27.05.2010, 16:56
это ничего не меняет (почти ничего)
серверному программисту надо правильным образом указать [XmlAttribute] в этом "одном-на-все-случаи-жизни" классе и все.

Получите все пропертис не в виде нодов, а в виде атрибутов. Одним из атрибутов, очевидно, будет тип объекта, чтобы было понятно, что с этим всем делать.

Там в примере все написано:


public class DataClass
{
public DataClass(){}
public string ID = Guid.NewGuid().ToString();
public string Name = "Just Name";
public Decimal Count = 10;
public DateTime Date = DateTime.Now;
}


дает

<?xml version="1.0" encoding="utf-8"?>
<DataClass xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ID>34332413-e70f-44f7-b35c-b34c47812dbc</ID>
<Name>Just Name</Name>
<Count>10</Count>
<Date>2006-10-30T12:35:20.3110319+03:00</Date>
</DataClass>


а всего навсего указание [XmlAttribute]:

[XmlRoot("Data")] // изменим имя корневого элемента
public class DataClass
{
public DataClass(){}

[XmlAttribute] // сериализуем в xml атрибут
public string ID = Guid.NewGuid().ToString();

[XmlAttribute] // сериализуем в xml атрибут
public string Name = "Just Name";

[XmlElement("Reserved")] // изменим имя xml элемента
public Decimal Count = 10;

[XmlIgnore] // не будет сериализоваться
public DateTime Date = DateTime.Now;
}


кардинально меняет картину:

<?xml version="1.0" encoding="utf-8"?>
<Data xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ID="cc340d5e-4c80-4fe5-9c3d-e49f64e26b22" Name="Just Name">
<Reserved>10</Reserved>
</Data>

Котяра
27.05.2010, 17:36
другое дело, что атрибутами можно задать только простые типы ( числа/строки)
а если это составной объект или массив?
тогда только нодами, но лучше сделать так:
<player type="object">
<posX type="integer">10</posX>
<name type="string"> vasya </name>
<pet type="object">
<posX type="integer">10</posX>
<name type="string">Шарик </name>
</pet>
</player>

litebox
27.05.2010, 17:37
Все это так, но класс нашего программиста выглядит примерно так:


public class ObjectClass
{
public List<PropertyClass> Properties { get; set; }
}

И все свойства объекта (поля, полученные из базы) просто добавляются в массив Properties, поэтому и после серриализации получается узел <properties>, где каждый дочерний элемент - элемент массива Properties, который является экземпляром PropertyClass, который, в свою очередь, серриализуется в виде, например, таком:
<property name="posX" value="10"/>
Поэтому серриализовать это в виде
<properties posX="10" posY="20" name="vasya"> или
<properties>
<posX value="10"/>
<posY value="20"/>
<name value="vasya"/>
</properties>
никак не получится, это нужно делать руками

mikhailk
27.05.2010, 17:44
мне вообще эта пара name->value здорово напоминает таблицу параметров настроек сайта... Но там их немного и требований по быстродействию нет...

Интересно, а такая технология, когда вообще все свойства всех игровых объектов лежат в текстовых полях одной таблицы, она вообще насколько широко применяется?

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

При этом, кстати, switch не нужен.
Просто проходите по списку пропертис и для каждого айтема берете name/value и делаете из них атрибут/значение в новом xml, который и используете далее.

Dimitry_II
27.05.2010, 22:20
litebox,
а чего бояться так "ручных" способов-то? Или используется стандартная библа, откуда выбирается функционал для формирования твоего модуля, или ручная обработка, которая точно также включается в код. Разве что если программер плохо оптимизировал код, то это как-то может сказаться на скорости, но уверю - не настолько, чтобы это почувствовал сам сервер.

А в принципе - если нужна скорость работы и оптимизированный код для сервера и клиента, то XML - худший вариант.

litebox
28.05.2010, 16:31
мне вообще эта пара name->value здорово напоминает таблицу параметров настроек сайта... Но там их немного и требований по быстродействию нет...

Интересно, а такая технология, когда вообще все свойства всех игровых объектов лежат в текстовых полях одной таблицы, она вообще насколько широко применяется?

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

При этом, кстати, switch не нужен.
Просто проходите по списку пропертис и для каждого айтема берете name/value и делаете из них атрибут/значение в новом xml, который и используете далее.

Да, именно по этому пути я и пошел, а читать поля, действительно, лучше без switch, где-то так:

for each(var n:XML in xl)
{
var varNameStr:String = n.@name;
var varTypeStr:String = n.@type;
var varValueStr:String = n.toString();

if(hasOwnProperty(varNameStr))
{
try
{
this[varNameStr] = varValueStr;
}
}
}

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

mikhailk
29.05.2010, 00:18
У серьезного приложения должен быть архитектор. Даже если этого человека нет, функции архитектора все равно кто-то выполняет. То, о чем Вы говорите - протокол взаимодействия клиент-сервер - как раз уровень компетенции архитектора.

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

Кстати, по поводу кода - а зачем try, да еще и в обрезанном виде?

litebox
31.05.2010, 12:33
В обрезанном виде он, чтобы не перегружать код примера лишним. Там реализован обработчик ошибки, если не получается присвоить данные.

mikhailk
01.06.2010, 00:56
Что-то мне интуитивно кажется, эксепшна там быть не может по определению.