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

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

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

Бинарный протокол ProtoBuf

Запись от Котяра размещена 22.05.2009 в 16:00
Обновил(-а) Котяра 25.02.2010 в 09:55

Не так давно (год назад), google предложил всем желающим использовать язык Protocol Buffers

Почитал, посмотрел - забавно. Перспективы использования большие.
есть порты на AS3, я тестировал этот:http://code.google.com/p/protobuf-actionscript3/

Хочу использовать как замену AMF.
В тестовом примере имитирую передачу данных по бинарному сокету.
Сразу появились проблемы: В том виде, как это сделано сейчас нормально можно работать только по схеме запрос/ответ, т.е. когда знаешь какой класс должен прийти в ответ.
При работе с "безымянным" сокетом в AMF можно узнать что за класс тебе пришел.
Попробуем реализовать это в ProtoBuf:
Все исходники тестового примера во вложении, здесь я акцентирую внимание, только на мои доделки)

итак главный класс: Main.as (читаем комменты)
Код AS3:
package 
{
	import com.google.protobuf.Message;
	import com.google.protobuf.Person;
	import com.google.protobuf.PhoneNumber;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.net.getClassByAlias;
	import flash.net.registerClassAlias;
	import flash.utils.ByteArray;
	import flash.utils.getDefinitionByName;
	import flash.utils.getQualifiedClassName;
 
	/**
	 * Тестовый класс работы с protoBuf - изменены исходники класса парсера
	 * @author k0t0vich
	 */
	public class Main extends Sprite 
	{
 
		public function Main():void 
		{
			if (stage) init();
			else addEventListener(Event.ADDED_TO_STAGE, init);
		}
 
		private function init(e:Event = null):void 
		{
			removeEventListener(Event.ADDED_TO_STAGE, init);
			// entry point
 
			//Регистрируем псевдонимы классов
			registerClassAlias("py.Person", Person);
			registerClassAlias("py.Number", PhoneNumber);
 
			// Создание и шифровка класса.--------------------------
			//write
			var person:Person = new Person();
			person.alias = "py.Person";
			person.setName("John Doe");
			person.setId(1234);
		    person.setEmail("jdoe@example.com");
 
			var number:PhoneNumber = new PhoneNumber();
			var number2:PhoneNumber = new PhoneNumber();
 
			number.setNumber("555-6789");
			person.addPhone(number);
 
			number2.setNumber("123123123-12312");
			person.addPhone(number2);
 
			trace("person: "+person);
 
			//Write it out to a any IDataOutput
			var bytes:ByteArray = new ByteArray();
 
			person.writeToDataOutput(bytes);
			trace("writed bytes: " + bytes);
			//-------------------------------------------------------
 
			// имитация прихода данных от сокета
			onData(bytes);	
 
		}
 
		//Данные от
		private function onData(bytes:ByteArray):void
		{
			bytes.position = 0; 
			//read
			var message:Message  = new Message();
			//читаем не всё сообщение, а только имя псевдонима
			var alias:String = message.readClassAliasFromDataOutput(bytes);
 
			var classRef:Class = getClassByAlias(alias) as Class;
			var item:* = new  classRef();
 
			bytes.position = 0; 
			item.readFromDataOutput(bytes);
			// выполняем метод конкретного класса
			item.changeModel();	
 
		}
	}
 
}
Что здесь добавлено: в примере от разработчиков нет поля псевдонима и поэтому узнать что за класс невозможно.
Делаем ход конем: вводим поле alias
Код AS1/AS2:
message Person {
  required string alias = 0;
  required string name = 1;
  required int32 id = 2;
  optional string email = 3;
 
  message PhoneNumber {
    required string number = 1;
  }
 
  repeated PhoneNumber phone = 4;
}
в базовом классе, от которого наследуются все сообщения в конструкторе регистрируем это поле и добавляем функцию его читающую.
Message.as
Код AS3:
.......
       public function Message() {
	  	if (fieldDescriptors == null)
		  	fieldDescriptors = new Array();	
			setAlias();
	  }
........
// регистрируем поле псевдонима
	public var alias:String ;
	public function setAlias():void 
	{
		 registerField("alias", "", Descriptor.STRING, Descriptor.LABEL_OPTIONAL, 0);	
	}
.....
 
	/**
	 * Прочитать псевдоним сообщения
	 * @param	input
	 */
	public function readClassAliasFromDataOutput(input:IDataInput):String {
	    var codedInput:CodedInputStream = CodedInputStream.newInstance(input);
		var tag:int = codedInput.readTag();
		if (tag == 0) return "";
 
		var fieldNum:int = WireFormat.getTagFieldNumber(tag);
	  	var desc:Descriptor = getDescriptorByFieldNumber(fieldNum);
		var item:* = codedInput.readPrimitiveField(desc.type);
		trace("item_alias "+item);
		return item;
 
	}
Затем в хэндлере onData (Main.as) вначале читаем имя псевдонима, создаем класс по этому псевдониму и в нём уже, читаем остальные данные

Код AS3:
private function onData(bytes:ByteArray):void
		{
			bytes.position = 0; 
			//read
			var message:Message  = new Message();
			//читаем не всё сообщение, а только имя псевдонима
			var alias:String = message.readClassAliasFromDataOutput(bytes);
 
			var classRef:Class = getClassByAlias(alias) as Class;
			var item:* = new  classRef();
 
			bytes.position = 0; 
			item.readFromDataOutput(bytes);
			// выполняем метод конкретного класса
			item.changeModel();	
 
		}
Я только день знаком с этим протоколом, поэтому просьба написать знатокам достоинства/недостатки итп..test_proto_buf.zip
Размещено в ru.k0t0vich
Комментарии 5 Отправить другу ссылку на эту запись
Всего комментариев 5

Комментарии

Старый 13.08.2009 16:02 undr вне форума
undr
Не подскажите, а какой версией вы пользовались?
Вы компилировали .proto файлы? Просто при компиляции .proto файлов компилятором этого проекта (http://code.google.com/p/protobuf-actionscript3/), результат получается плачевный. Код с синтаксическими ошибками. Типа:
Код AS3:
private memoizedSerializedSize:int = -1;
public getSerializedSize():int {
...
}
и
Код AS1/AS2:
public void writeTo(com.google.protobuf.CodedOutputStream output)
{
...
}
Плюс, куча ошибок компилятора, типа, 1120: Обращение несуществующего свойства hasblablabla.

Как Вы компилировали .proto файлы? Как Вы получили классы Person и PhoneNumber?
Старый 18.08.2009 15:34 Котяра вне форума
Котяра
 
Аватар для Котяра
Нет. классы я писал ручками.
во первых, как вы уже заметили, компилятор глючный, во вторых я добавляю вручную необходимые мне ф-ции changeModel
До компилятора пока руки не дошли. переделывать его всё равно буду, т.к. у меня будет версия с расширением протокола ProtoBuf -> ProtoBuffWithAlias, причем для компиляции как as, так и py классов
базовые классы тоже прописаны ручками.
Кстати. у меня в коде баг. alias не обязательно будет писаться в поток первым, хотя у него и id=0, т.к. запись идет не по id а по forin.
Как сделаю компилятор выложу изменения здесь.
Обновил(-а) Котяра 18.08.2009 в 15:38
Старый 22.02.2011 15:43 kyzi007 вне форума
kyzi007
А поодержку Number случайно не делали?
Оно их не пишет(
Старый 26.01.2012 03:21 Dukobpa3 вне форума
Dukobpa3
 
Аватар для Dukobpa3
А можешь описать бонусы протобуф по сравнению с амф?
Я прогуглил то как-то хз. Авторство гугла для меня не есть показатель. А по остальным параметрам как для связки Flash-SomeThing - AMF рулит.

А, ну еще протобуф сам код генерит.
Старый 15.03.2012 12:18 ir73 вне форума
ir73
Котяра, как успехи с протобафом? Стоящая вещь?
 

 


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


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