Как стать автором
Обновить

Комментарии 69

Почему-то, после слов «json слишком жирно» я не услышал слова bson, который, как раз для этого и предназначен.
Так я изначально не предполагал использовать готовое. Поэтому вскользь упомянул некоторые существующие варианты и дальше не стал распространяться.
Ибо если описывать все существующие варианты с их плюсами/минусами еще с десяток статей придется написать…
(вы про «десяток статей» говорите так, как будто это что-то плохое)

А в моём представлении, если есть готовое, надо использовать его, а не изобретать велосипед.
Свой вариант можно бесконечно оптимизировать (в свободное от работы время, конечно), вплоть до пакетов в 1 байт. А «готовое» приходится кушать в том виде, в каком его подают, со всеми наворотами.

Даже если «готовое» имеет открытый исходный код, т.е.у нас полный контроль над будущим развитием проекта, то всё равно простые вещи лучше делать с нуля, чем упрощать сложные инструменты для отправки пакетов в 1-10 байт.
Я правильно понимаю, что нет никаких других проблем, кроме как повторного написания простых вещей? Либо вы пишите что-то новое, что до вас не писали (или у вас нет возможности его использовать), либо вы бесконечно оптимизируете свой вариант того, что уже реализовано.
В данном случае, подумав, автор решил что 7 байт достаточно. Зачем использовать готовые решения, которые занимают дополнительные затраты на упаковку/распаковку, когда нужно всего лишь, грубо говоря, получить 7 чисел?
Полностью согласен про велосипеды. И если бы вы внимательно прочитали мой пост, то заметили бы, что я рекомендовал использовать готовые протоколы.

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

P.S. А вообще, из любого правила есть исключения. Не всегда готовое, лучше придуманного вами велосипеда.
> (вы про «десяток статей» говорите так, как будто это что-то плохое)

Вот и напишите про них. Все будут вам только благодарны.
Что интересно в случае, когда у нас много маленьких сообщений, JSON компактее BSON.
"{foo:'bar'}" — 11 байт, в BSON'е это 18 байт.
"{cid:1,uid:12,x:10,y:20}" — 24 байта так, и 53 в BSON.
"{cid:1,uid:12,c:[10,20]}" — 24 байта, и 61 в BSON.
Может проще обозначить какие данные у нас есть и декодировать и кодировать их самим?
Например я ни разу не видел чтобы слали что-то кроме string, int и float в качестве переменных.
Почему бы не обозначить их 0+ 32 битная длина сообщения+само сообщение; 1 и 2+32 битное (если необходимо, если нет, можно и меньше сделать) число. И парсить уже вручную разбиением по размерам. В итоге и размер минимален и данные все отосланы. Длину всего сообщения можно указывать в начале всего сообщения, кодируя в текст.
Так работает сериализация в пхп, грубо говоря, и в некоторых случаях она проигрывает по скорости распаковке JSON. И учитывая что там нативно все это делается, то ручная разборка займет дополнительное время + рессурсы, что для сервера критично, проще упростить формат, чем докупить железа.
Ну на пхп писать, неблагородное дело :) я реализовывал на python.
До конвертации в cython, к моему сожалению, не дошли деньги клиента.
> Что касается бинарных протоколов, то в них нет разметки как в XML или JSON

ASN.1 DER
Отмечу также замечательный проект asn1c Льва Валкина, который генерирует код на C и других языках по спецификации.
Только на C генерирует. Вот здесь, в двух статьях про LDAP, есть подробнее про ASN.1 и asn1c: fprog.ru/2011/issue7/
И ещё, если уж решили изобретать свой протокол, то где поле «номер версии протокола»? «Нет планов развития» — не ответ (это сегодня их нет).
Тогда уж надо придумывать механизмы горячего обновления кода и поддержки на сервере двух протоколов одновременно.
поддержки на сервере двух протоколов одновременно.

Зачем?

У нас же в игре веб-клиент. Просто делаем технологическое окно в работе сервера и отдаём пользователю новую версию клиента и всё. Для уменьшения проблем с кешированием — каждой новой версии клиента даём уникальный URL.

Тем бедолагам, у кого клиент по какой-то причине не обновился, даём ссылку на страницу «Как очистить кеш браузера».
В этом просто нет необходимости.
На самом деле, такое поле необходимо в очень редких случаях. Например в платежной системе, где могут быть клиенты построенные на разных технологиях, с разными возможностями. И где количество передаваемых пакетов не велико по сравнению с игрой.

А в игре передавать версию это лишь бессмысленно нагружать канал связи. Вполне достаточно при авторизации передать версию клиента и если она старая, то обновить. И без обновления не пускать клиента на сервер.
Или вы будете пускать на сервер разные версии клиента? А какой в этом смысл? В этом случае поведение клиентов будет различным, а это недопустимо в игре.
> Вполне достаточно при авторизации передать версию клиента и если она старая, то обновить. И без обновления не пускать клиента на сервер.

В простейшем случае — да. Где это в статье?
Во первых это не в простейшем случае. А во всех случаях. В игре просто нет смысла в многоверсионности протокола.

А во вторых… ну когда же наконец вы научитесь читать?

Я же русским по белому писал. что это не пошаговый туториал к коммерческой игре… тут и обновления клиента не будет… тут вообще много чего не будет, что необходимо игре как коммерческому продукту.
А когда вы научитесь писать? Если статья для профи, которые и так знают как разрабатывать протоколы — то ваша статья им не нужна. Если статья для новичков — то лучше вообще не писать, чем недоговаривать.
товарищ, не интересно, не читай. Сейчас обидишь человека, он не станет продолжать, а мне очень интересно. Пишет хорошо.
Местами ерунду пишет. Кто-то его прочитает и сделает как он написал. А мне и вам потом этим пользоваться.
Фигню говорите. Тот кто на таких статьях пытается сделать коммерческий продукт как говорится ССЗБ… Именно поэтому я не хотел выкладывать изначально полные исходники. Ибо придут такие как вы и будут ныть что всё плохо… не разжевали и в рот не положили…

Помните поговорку? «Дайте пожалуйста по пить, а то так кушать хочется, что переночевать негде… да и не с кем...»
так вот она про вас.

Можете написать лучше меня? Возьмите и напишите. Люди будут благодарны. Я тоже с удовольствием почитаю и поучусь…

А ныть каждый может…
> Тот кто на таких статьях пытается сделать коммерческий продукт как говорится ССЗБ

Значит, вы считаете, что на хабр стоит выкладывать только малоинформативные статьи про то, как сделать полурабочее нечто?

> Можете написать лучше меня? Возьмите и напишите.

«Не нужно быть поваром, чтобы сказать, что суп пересолен.» И откуда вы знаете, что я не пишу?
Я вижу, что вы пишете.
На счет малоинформативности:
1. Это не последняя статья.
2. Это не статья про то как вообще делать игры.
3. Это статья про клиент серверное взаимодействие scala и flash.
Просто не хотелось писать сугубо теоретические выкладки. Гораздо интересное практическое применение. Теории в инете достаточно.
4. Да, я считаю, что лучше человеку указать направление и показать примеры, чем давать готовое решение. Ибо его скопипастят даже не разобравшись и вам по вашим же словам этим потом пользоваться.
И в конце концов сегодня мало народу на хабре.
Завтра люди почитают мой топик и плюсами скажут надо ли продолжать.

Если я плохо пишу, то это будет последняя статья. Вот и все. Все очень просто.
Я где-то говорил что вы плохо пишете? Я сказал, что у вас есть типичная ошибка, которую делают при проектировании протоколов, форматов файлов и прочих форматов кодирования информации: отсутствие поля с версией протокола. Даже если нет поддержки нескольких версий одновременно, это поле всё равно нужно, чтобы старый клиент (например, из кеша, если говорить про веб) не парсил новый протокол, а прямо сказал пользователю «нажми F5» (или дёрнул JS). Или если при деплое вы задеплоите старый сервер и у клиентов начнутся непонятные ошибки (а если протокол поменялся чуть-чуть, они будут только «если пойти туда, иметь при себе то-то и сделать то»). Или если при отладке запустить неподходящую комбинацию. Вариантов того, как могут встретиться неподходящий клиент и сервер — море, а всего одна проверка избавит вас от необходимости совершенно ненужной отладки.
А я вам тоже говорю, что версия протокола в играх нужна как зайцу стоп сигнал…
Ну нафига каждый! пакет передавать версию, зачем трафик увеличивать? Это только при логине надо. Абсолютно все варианты того, как могут встретиться неподходящий клиент и сервер можно предусмотреть простыми превентивными мерами.

Но в любом случае, у меня статьи не про проектирование протоколов на все случае жизни. А про вполне конкретный пример клиент серверного взаимодействия.
Ну конечно же только при логине, один раз. Я и не говорил что в каждом сообщении. Как версия клиента может поменяться не разрывая TCP соединение? Никак.
Недоговаривать чего? То о чем вы пишете нафиг не надо в игре.

> Если статья для новичков — то лучше вообще не писать
Во первых я пишу о том, о чем считаю нужным. Кто вы такой вообще чтобы указывать кому и о чем писать? От вас даже ни одного толкового камента не было… одно нытье… обидели его видите ли… не дали готовый пример который можно толкнуть тут же на вконтактик и «грести бабло»…
Нормальному новичку этого вполне хватит чтобы начать разбираться в тему и додумать все что необходимо… а разным нытикам даже полный исходный код готовой игрушки не поможет… тупо скомпилить не смогут и опять же будут ныть что плохо написано…

Есть что толковое написать? Добро пожаловать в каменты. Я всегда рад конструктивной критике. Нет? Проходите мимо, не засоряйте топик…
Все-таки, как понимаю, у вас будет записываться движения танка на сервере. При движении вы будете выдавать постоянно где он находится? Тогда получится сильная генерация трафика, что скажется не очень хорошо. Было бы лучше, если бы вы на сервер отправляли всего лишь например: команда движение/направление и команда стоп. Тогда вы можете контролировать сервером его движение, непреодоление стен (чтобы в игре не возникало игроков-призраков). Также реализация стрельбища: можно выдать только направление полета пули (в какую сторону стрельнул игрок) и все. Сервер знает координаты танка и сам, в принципе, подсчитает направление движения, встречу и т.п.
Таким образом получается для клиента:
ИД команды
Ид клиента

Для сервера:
1. Подтверждение авторизация
2. Координаты танкОВ противникОВ и его состояние (живой/убит), (x,y,s)

3. Команда «в нас попали»
4. Количество игроков
5. Отключение клиента по запросу
Простите, случайно отправил.

Для сервера можно сократить до

Подтверждение авторизации или дисконнект.
Массив танков, следственно количество игроков
ID команды для вашего танка.
И еще добавлю:

Поскольку массив танков надо постоянно обновлять, т.к. игра не пошаговая, а реального времени, то в данном массиве должны быть переданы только случившиеся изменения, чтобы не занимало большой объем трафика и постоянной разборки.
Именно так и будет. Будут только дельта изменения. ну и периодическая (например раз в 5 сек отправка если ничего не происходит для подтверждения, что клиент не отвалился)
Да скорее всего так и будет. Будем передавать команду начала движения и окончания.
НЛО прилетело и опубликовало эту надпись здесь
Полностью с вами согласен. Это лишнее значение.

Также хочу подметить:
Координаты танка при движении (х, у)

Забыли поворот танка. Или он всегда в одном направлении?

Координаты выстрела (х, у) место в котором игрок нажал огонь, чтобы рассчитать на сервере было ли попадание

У вас танки из рейлгана палят? Что при выстреле уже попадание можно рассчитать? Не правильнее ли тут добавлять объект «снаряд», столкновение с которым и будет приводить к повреждению противника?
Да, в данный момент будет именно рейлган. ))

В сотый раз говорю… Повествование будет от простого к сложному. Сначала сделаем совсем простой вариант. Тупо в лоб не взирая на оптимизации и прочее.
А потом проведем рефакторинг и доедем до ума и сервер и клиент.

Думаю так будет правильнее, чем просто выложить очередной туториал типа «напишите это и то и получишь свою контру»
Хм… логично. Спасибо за подсказку. Так и сделаю в продолжении.
Делается авторизация сначала, потом работа по уникальному auth hash (сессии в пхп так работают) от сервера :) его не подделаешь.
скала приятная. аж захотелось попробовать с ней поработать.
Для игровых протоколов лучше будет использовать UDP, а не TCP соединение.
Не подскажете, а в какой версии флеша появилась поддержка UDP?
Их пока нет (кроме как для RTMP через Flash media Server и там еще ограничения).
Если речь идет о флешевом приложении, в виде самостоятельного приложения, то можно использовать www.multidmedia.com/software/zinc/ тогда будут UDP сокеты.

В реальности, далеко не всегда UDP как раз нужны.
Зачем zinс? DatagramSocket есть и в Air.
И зачем тут UDP? :) Сессионость самому реализовывать? Или checksum слать?
Думаю, ребята из Valve дадут вам исчерпывающий ответ, по опыту Half-Life и других игр, я лишь скажу, что UDP сильно снизит лаги смой игры (TCP пакет может не доставится и пересылаться, что занимает время), снизится нагрузка на сетевое оборудование.

Сессионность как будто так сложно реализовать? Уникальный ID, а лучше и несимметричная криптография решит все проблемы. Обмениваетесь открытыми ключами в начале игры, подписываете все пакеты от сервера к клиенту и обратно, в самом пакете поле уникального ID. Итого у вас на руках для идентификации посылающего: IP, port, ID, валидность подписи. Кажется, более чем достаточно!

Нужно делать сразу хорошо, чтобы мучительно все не переделывать при развитии проекта.
Отлично. Покажите мне как ребята из Valve сделали UDP на флеше. Особенно хотелось бы посмотреть Half-Life на флеше с UDP…

Прежде чем писать такие вещи, неплохо бы почитать о чем вообще топик…
И какая тогда выгода, если Вы еще и криптографию сверху накините?
Уверен на коллизиях и переотправках данных теже самые решения как и TCP будут, особенно для Флеша.
Многие реалтайм протоколы сделаны не на UDP, потому что последующий оверхед добавления сессионости и других защит TCP к датаграммам приведет к тому же толстому TCP.
Умейте использовать инструменты UDP, SCTP, TCP, RTMP и т.п. из них нет одного идеального решения, все подходят под разные процедуры.
А то с Вашим подходом, проще свой протокол 3 уровня разработать. Или лучше вообще байты по ether слать с собственной рутинг сетью.
Короче говоря не убедили. Если надо будет делать игру с стреляками, то UDP король. Но в случае поинт и клик онлайн заморочки и затраты не окупятся.
По-мимо этого флеш нативно не любит UDP
Разрабатывали протокол тоже. Только еще добавили check_id, в него закодирована версия протокола и последовательность сообщения, легкая защита сиквенса сообщений зато полезно от кулхацкеров.
И еще одно очень главное.
2500 игроков без zlib делали 300 мегабит, с zlib 20-60 mbit… Компрессию сразу надо включать. Нагрузка незаметна, а экономия и скорость в разы увеличивается.
о, это интересно. А какие объемы одного пакета? как будет вести себя zlib, и вообще, компрессия в случае множества мелких фрагментов? И нагрузка на CPU раскодирования всего? Как раз думаю, стоит ли заниматься
Нагрузка минимальная (разницы особой замечено не было), правда в связи с «понятливостью» флешера пришлось слать AMF пакеты. Думаю на мелких пакетах (где нет тонны информации как с AMF) проще слать без шифрования, ибо до по-моему 1 кбайта эффективность низкая у дефлейта будет.
Под низкой эффективностью имел ввиду, что размер пакета даже больше будет.
И да, забыл добавить, лучше сделать фоллбэк на http. Дело в том, что не все «клиенты» смогут играть в TCP режиме. Даже на 80 порту. Так как обычно режут все и оставляют только 80 порт. Что самое страшное режут и CONNECT режим. Вариант только один, делать и TCP и HTTP соединение на одном 80ом порту.
да, есть такое. Лучше, кстати, перевести на 443 порт, еще часть клиентов могут не HTTP-траффик пускать только так.
У вас наверно что-то типа XML было раз такая разница? Просто в нашем случае компрессировать то нечего… 7 байт всего )))
Но в общем случае это полезно.
до 64 кбайт доходило, AMF чтоб его :).
Solver, продолжайте — это интересно.
Эх, на пару месяцев бы пораньше и я бы так не мучался со своим курсовиком. =)
Очень круто и интересно. Не слушайте всяких грибозавров, продолжайте. Единственное, я так и не понял, зачем следует использовать свой «велосипедик» вместо мощного и удобного протобафа? Для java реализация есть, для флеша, пусть и кривоватая, – тоже.
Хотя, оперевшись на внутреннюю реализацию protobuf, велик соблазн не разбираться, как оно работает. А цель у ваших статей, насколько я понял, другая.
Но наткнувшись на пару неприятных багов флешовой реализации, в любом случае придется залезть внутрь и разобраться :)
И еще вопрос: будут ли применяться юнит-тесты на стороне сервера? Мне, как флешеру, они знакомы только понаслышке. Было бы очень здорово попробовать их на зубок в рамках этого проекта
Юнит-тесты будут только на сервере.
Да-да, я про сервер и говорю
И еще:
1. В ClientHandler функция называется act, а запускаете new ClientHandler().start().
2. addEventListener(DataEvent.DATA) -> addEventListener(ProgressEvent.SOCKET_DATA). Socket не диспатчит событие DataEvent.DATA
Следующая часть так и не вышла? Или я ее пропустил?
Следущая часть задержалась немного ))
Выйдет на днях
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации