Форум Flasher.ru
Ближайшие курсы в Школе RealTime
Список интенсивных курсов: [см.]  
  
Специальные предложения: [см.]  
  
 
Регистрация Блоги Правила Справка Пользователи Календарь Поиск рулит! Сообщения за день Все разделы прочитаны
 

Вернуться   Форум Flasher.ru > Блоги > КорДум

Оценить эту запись

Бинарные сокеты в AS3. Часть 1

Запись от КорДум размещена 13.07.2012 в 23:19
Обновил(-а) КорДум 16.07.2012 в 13:27

Часть 2. Часть 3.

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

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

Штука очень привлекательная и не стоит ее бояться. Если глянуть на википедии, то там не так уж много вменяемой понятной непосвященному информации. Посему осмелюсь сказать своими словами: сокет — это просто непрерывный канал, по которому передаются то в одном, то в другом направлении (от сервера к клиенту и наоборот), а то и одновременно в двух (полнодуплексный сокет) сплошные сырые байты. Передаются они по определенному протоколу: UDP или TCP. Первый хорош тем, что сообщения летят сразу раздельными такими пакетами. Но он совершенно не гарантирует, что пакет дойдет до адресата. Кроме того, в UDP нужно следить за последовательностью отправки сообщений, так как они могут вообще перемешаться, контрольные суммы для проверки целостности нужны… Честно, я не вдавался в подробности. В отличие от TCP, где гарантия есть, а битость отдельных частей восстанавливается. Однако в TCP пакеты могут приходить частями (если не влезают в значение MTU), быть склеенными (несколько мелких сообщений в одном или одна большая часть сообщения (1 пакет) и концовка + маленькое сообщение (2 пакет)).

Так вот. Самое простое, что можно придумать: это считывать данные, пока не встретится какой-то определенный символ. Таким символом, как правило, выступает нулевой байт «\0». Естественно, этот нулевой байт нужно вшивать в пакет в конце каждого сообщения. Нулевой байт в шестнадцатеричном представлении — 0x00. Убогость этого способа в том, что можно передавать только строки в UTF-8 и все. Нельзя вшивать (именно вшивать, не помещать в строку) в сообщение, например, дробные числа типа float, так как они содержат в себе несколько нулевых байтов (если я не прав, обязательно сообщите мне, я тут же исправлюсь) Но, не исключаю, это самый наипростейший вариант: читаем, пока не встретился нулевой байт. Встретили, записали в буфер полученные данные, пустили на парсинг байты снова. И так каждый раз.

Когда я только-то задался вопросом обмена данными между клиентом и сервером через сокеты, ребята-флешеры отговорили меня (вру, не отговаривали, они мне сразу начали объяснять другое), рассказали про другие «методы». Впоследствии уже, с опытом, я понял, что они были правы и этот способ не только удобнее, но и симпатичнее (хотя реализация его достаточно трудна с непривычки). Я им всем достаточно компостировал мозги, пока не познал, хех, дао и не научился вменяемо ловить от сервера и отправлять туда же свои сообщения.

Кроме обычного бинарного сокета в AS3 есть XMLSocket. Он примечателен тем, что все сообщения представляют собой обычные UTF-8 строки с кучей XML мусора вокруг и нулевым байтом в конце. Он, по идее, проще. Так как не нужно задумываться о всяких байтиках, пакетиках и прочей приблуде. Но все сообщения возрастают в размерах за счет XML-оберток и, как следствие, возрастает трафик. Неудобно, по моему скромному мнению. К делу!

Так как тут есть какие-то ограничения по количеству символов в статье, я разобью ее на несколько частей.

Часть 2. Часть 3.
Размещено в net
Комментарии 22 Отправить другу ссылку на эту запись
Всего комментариев 22

Комментарии

Старый 14.07.2012 01:50 Котяра вне форума
Котяра
 
Аватар для Котяра
сиськи где?
Старый 14.07.2012 02:02 КорДум вне форума
КорДум
 
Аватар для КорДум
Они в теме про MVC у Тигры =)
Тут просто всякая фигня про сокеты и очень полезные комментарии ))
Старый 14.07.2012 21:12 dark256 вне форума
dark256
 
Аватар для dark256
Корд.... символ НОЛЬ в float и собссно НУЛЕВОЙ байт - это разве не разные вещи?
Кодировка символа ноль как бы несколько иная, вообще-то.
Старый 14.07.2012 21:20 КорДум вне форума
КорДум
 
Аватар для КорДум
Про float не в курсе. De же говорил про нулевые байты в вещественных числах.
Про символ "0" в UTF-8 ничего не говорю (а хотел написать). У нуля код 0x30 =)
Старый 15.07.2012 11:55 dark256 вне форума
dark256
 
Аватар для dark256
Хм. Странно. Кстати, чем бинарник лучше ХМЛ-сокета?
Старый 15.07.2012 12:41 КорДум вне форума
КорДум
 
Аватар для КорДум
Гибче, байтов меньше передается. В сообщении не может быть нулевых байтов, кроме как в конце (это обычная UTF-8 строка с кучей xml хлама. На сервере придется тоже каждое сообщение в xml оборачивать. Бесконечно парсить.
Но, в то же время, XML-сокет намного проще в использовании.
Старый 15.07.2012 15:50 ramshteks вне форума
ramshteks
 
Аватар для ramshteks
основное преимущество бинарного сокета перед "строковым" коим и является XML-сокет это его минималистичность. Он компактнее и не страдает избыточностью, о чем и сказал КорДум. С другой стороны, есть большая проблема это дебаг такого сокета. Строковый достаточно вычитать и вывести в консоль, чтобы знать что прислал нам сервер или клиент, с бинарным такой фокус уже не выйдет, так как просто напросто для каждой последовательности нужен парсер в котором и может быть ошибка, что значительно осложняет поиск ошибок. И проблема даже не столько в парсинге, хотя это тоже не маловажно.

О гибкости я бы не стал говорить, потому, что сами по себе протоколы не являются гибкими. Вернее можно сделать в определенном смысле гибче, но нельзя забывать, что гибкость подразумевает минимальное количество изменений все таки при новых требованиях, а такое вряд ли возможно, что для одного вида протоколов, что для другого. Так как изменение протокола ведет, не только к изменению логики(на сервере и клиент), но правках в способах, чтения, записи(и там и там), а так же дополнительные проверки на сервере, этих самых входных значений. По сему, тут стоит говорить не столько о гибкости, сколько об удобстве использования и требованиях к самой системе, насколько для нее критично передать лишние 10кб, когда можно было 1кб.
Старый 28.07.2012 03:08 Dukobpa3 вне форума
Dukobpa3
 
Аватар для Dukobpa3
Цитата:
нужен парсер в котором и может быть ошибка, что значительно осложняет поиск ошибок.
Не думаю что это столь сложно. К тмоу же можно пользовать стандартные упаковщики для которых куча либ есть. BSON, AMF, ProtoBuf. Они и будут парсить в обе стороны.

Если совсем уж бинарный по своему формату тоже проблем нет главное не полениться и потрейсить байтики полученные и отправленные. Сама функцийка такого трейса из трех строк состоит. Думаю это не оч сложно.
Старый 28.07.2012 15:04 КорДум вне форума
КорДум
 
Аватар для КорДум
Код AS3:
override public function toString():String {
	var text:String = "";
 
	for (var i:uint; i < length; i++) {
		text += this[i] + " ";
	}
 
	return text;
}
Угу. С удивлением обнаружил как-то, что нельзя дебаггером глянуть содержимое байтАррея. Да что там дебаггром, оттрейсить через нативные средства тоже не предоставляется возможности. Ну и вот пришлось заоверрайдить toString().
Старый 28.07.2012 15:14 ramshteks вне форума
ramshteks
 
Аватар для ramshteks
да дело не в том, что нельзя глянуть. Дело не в том, что для того чтобы вывести нужны телодвижения. А в том, что вот лично мне, будет тяжело взгянув на 8 байт в hex вычитать из него тот же дабл. Если это только для меня проблема, тогда да, ребят - дебагинг бинарных протоколов не проблема вообще
Старый 28.07.2012 16:49 Dukobpa3 вне форума
Dukobpa3
 
Аватар для Dukobpa3
Тебе не нужно взглянув на 8 байт увидеть дабл. Тебе нужно взглянув на каких-то тестовых 20-30 байт, которые ты отправил с сервера, а потом взглянув на 20-30 байт которые ты получил - просто напросто увидеть одну и ту же последовательность цифр.
Старый 28.07.2012 21:21 ramshteks вне форума
ramshteks
 
Аватар для ramshteks
то есть вы считаете, что прыгать между выводом двух IDE что бы сравнить "каких то" 20-30 байт, по нескольку раз во время процесса дебагинга это нормально и никаких затруднений не вызывает? И может это и не так проблемно если у вас одна команда, но вот если вам надо отдебажить 30-40 команд, которые состоят из нескольих по порядку записанных структур, и размером 50-100 байт, то удачи вам с вашим методом.Я понимаю ваше желание защитить свою точку зрения, но вы порите чушь, уж извините. Это общеизвестная проблема бинарных протоколов. И она есть, и есть варианты решения вроде вашего, но от этого эта проблема не перестает быть таковой
Старый 28.07.2012 21:40 Dukobpa3 вне форума
Dukobpa3
 
Аватар для Dukobpa3
Цитата:
если у вас одна команда, но вот если вам надо отдебажить 30-40 команд
Дебажить таким вот образом каждую команду это бред. Протокол пишется один раз. Всё чего нужно добиться на этом этапе - чтобы на выходе сервера и входе клиента были одни и те же данные. Таким же образом и в обратную сторону.

Отладка самих команд к протоколу мало отношения имеет. И там уже более высокоуровневые инструменты, которым, как бы, пофигу - там строка пришла или байтики, или файлик, или еще какая херня.

//*********************************
К слову, работал со строками (джейсон гоняли, и хмл), работал с тремя бинарными протоколами(АМФ, протобуф, БСОН). При этом всём закодировать/раскодировать месадж это максимум 50 строк кода в отдельном классе упаковщика.
Далее этот упаковщик пристегивается к какому-то сервер-контроллеру или коннектору. А вот коннектор даже не знает в каком формате по сети данные кгоняются. Коннектор отдает упаковщику вменяемый пакет, некую структуру которую понимает сервеКонтроллер и всё что рядом с ним. Из упаковщика получает "нечто" упакованное по правилам протокола, и всё что остается сделать это запихнуть это "нечто" в сокет.

Так вот не надо путать отладку упаковщика, которая производится именно так как я описал, с отладкой неадекватности самих команд.
В случае с текстовым протоколом этот упаковщик просто не вмешиваясь выдаст то, что получил, например. А может распарсить джейсон и выдать обжект. Я делаю так чтоб упаковщик выдавал вменяемый класс наследник какого-то базового Message, который уже сразу можно будет использовать.

Если каждая команда по-разному пакуется - это косяк архитектуры, а не сложности "общеизвестные".
Старый 29.07.2012 15:42 ramshteks вне форума
ramshteks
 
Аватар для ramshteks
я вам об одном, вы мне о другом. Я не говорю что это невозможно, я говорю что есть ряд сложностей связанных с тем, что данные бинарные. Уверяю вас, ошибиться можно и в 2 строчках кода упаковщика, по запаре написав вместо writeShort - writeInt, а потом удивлятся почему приходит херня. И тут вы хоть о стену расшибитесь имея самую лучшую архитектуру в мире, а выяснять прийдется, притом не самым приятным образом.

А еще, я не знаю с какими проектами вы работали, но протоколы меняются, крайне не охотно, но меняются и порой координально, и в таки моменты начинается увлекательное путешествие под названием "отладка протокола"
Старый 30.07.2012 01:10 Psycho Tiger вне форума
Psycho Tiger
 
Аватар для Psycho Tiger
Цитата:
я вам об одном, вы мне о другом.
Да как то вот я понимаю Dukopba3, но не понимаю тебя. Когда ты говоришь спрайту поменять координату – у тебя же не возникает мыслей о том, что, возможно, произойдёт ошибка, что Adobe по запарке сделали неправильно, а дебажить (если можно было бы) сложно, потому что всё уже скомпилено и упаковано?

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

В конечном счете, разговор сводится к сложности отладки бинарных данных. Только мне совсем неясно, как, почему и зачем глядя на голые байты судить о чем-то. В нормальном коде не встречается такое:
Код AS3:
var a = byteArray[0];
var b = byteArray.position > 3 ? byteArray.readShort() : 0;
byteArray.position = 8;
var c = byteArray.readInt();
Данные подготавливаются в соответствии с синтаксисом пришедшей команды, а потом с ними работается.
Код AS3:
var itemId:int = byteArray[0];
var itemPrice:int = byteArray.readInt();
И дебажатся уже конкретные данные, без прямого взгляда на бинарный протоколом.
Код AS3:
trace(itemId,itemPrice);
itemPrice отрицательный? Значит, ошибка с 1 по 4 байт. Уже нашел. И как-то нет разницы, текст, XML или байты.
Старый 30.07.2012 01:17 Psycho Tiger вне форума
Psycho Tiger
 
Аватар для Psycho Tiger
Цитата:
А еще, я не знаю с какими проектами вы работали, но протоколы меняются, крайне не охотно, но меняются и порой координально, и в таки моменты начинается увлекательное путешествие под названием "отладка протокола"
В реальных проектах описаных примеров выше нет. Пакуется в AMF и сжимается, например. Причем этот пекеджер - сменная штука. Проще говоря, в коннектор уходит пакет
Код AS3:
connector.send(packet:Packet);
а коннектор его сериализует, в соответсвии с протоколом:
Код AS3:
serializator.serialize(packet);
По приходу от сервера - пакет им же десереализауется:
Код AS3:
serializator.deserialize(packet);
Соответственно, завтра перешли на JSON - меняется и отлаживается один класс.

Если ты говоришь о случаях, когда протокол кардинально меняется: например, с raw-бинарного, который я предложил выше - вот в AMF - то это действительно сказки. Разве что увидели полную несостоятельность подхода - но это тот случай, в которой проблема в квалификации разработчиков, которые разработали несостоятельную архитектуру.
Старый 30.07.2012 06:25 ramshteks вне форума
ramshteks
 
Аватар для ramshteks
Ок, хорошо, убедили, никакой разницы между символьным и бинарным протоколом нет. Особенно если использовать протоколы типа AMf или Protobuf
Старый 30.07.2012 16:10 Dukobpa3 вне форума
Dukobpa3
 
Аватар для Dukobpa3
Реальный пример. Вот месяц назад писал новый упаковщик.
Достаточно было отправить примерно след структуру:
ИдКоманды: 1
Статус: 1
данные: {
"id":8
}

в итоге получаем пакет что-то около 20 байт в длину. Разложили это в трейсе в массив по одному байту. В трейс попал массив из 20-и значений и гоняли туда сюда и трейс смотрели. Чтоб отладить протокол - этого вполне хватило. И я думаю не сложно даже по битам расписать что там ты хочешь увидеть - это не большая структурка, а большая тебе ничем не поможет на данном этапе.

Все заголовки пакуются по своим правилам, а то что находится в "данные" - BSON. Проблемы были только на этапе запихивания в БА, надо было правильно сформировать заголовок, записывать каждую часть заголовка в нужном порядке и в нужном размере/формате.

Примерно так происходит и с любым бинарным протоколом.
Старый 30.07.2012 22:36 dimarik вне форума
dimarik
 
Аватар для dimarik
порой координально [x]

Кстати, AMF3 вполне себе хорошая, годная штука. Только в длине алиаса и названий полей не переусердствуйте. Он не позиционный.
Старый 31.07.2012 01:17 gloomyBrain вне форума
gloomyBrain
 
Аватар для gloomyBrain
dimarik, а разве кеширование не спасает от таких проблем? Ну то есть - в AMF3 поддерживается кеширование на уровне плеера. Равно как и сжатие строк. Я так понимаю - главное чтобы сервер был готов.
Старый 31.07.2012 20:55 Dukobpa3 вне форума
Dukobpa3
 
Аватар для Dukobpa3
Цитата:
Кстати, AMF3 вполне себе хорошая, годная штука.
Проводили тесты с посонами. АМФ петоном пакуется 8.7 каких-то там единиц времени по сравнению с 1.6 БСОН.

Плюс длина пакета аналогичного содержания амф слегка поболее будет чем того же бсон.
Старый 01.08.2012 13:56 gloomyBrain вне форума
gloomyBrain
 
Аватар для gloomyBrain
Кстати, каксательно BSON, он тоже слегка избыточен. Мне лично больше всего нравится msgPack
 

 


Часовой пояс GMT +4, время: 14:51.


Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2018, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.