Бинарные сокеты в AS3. Часть 3
Часть 1. Часть 2.
Ага. Packet – просто удобная штука для хранения информации, формирования массива сырых байтов и всего такого прочего. Он чрезвычайно прост и представляет собой «абстрактный» класс для всех других пакетов, имеющих уже каждый свой тип.
package client.net.packets { import flash.utils.ByteArray; /** * @author KorDum */ public class Packet { public static const SOME_PACKET:uint = 0x00; // другие константы private var _length:uint; private var _type:uint; private var _data:ByteArray; //--------------------------------------------------------------------------- // // CONSTRUCTOR // //--------------------------------------------------------------------------- public function Packet() { } //--------------------------------------------------------------------------- // // PUBLIC METHODS // //--------------------------------------------------------------------------- public function getByteArray():ByteArray { var buffer:PacketByteArray = new PacketByteArray(); buffer.writeLength(_length); buffer.writeType(_type); buffer.writeBytes(_data); return buffer; } //--------------------------------------------------------------------------- // // PUBLIC ACCESSORS // //--------------------------------------------------------------------------- public function get type():uint { return _type; } public function set type(value:uint):void { _type = value; } public function get length():uint { return _length; } public function set length(value:uint):void { _length = value; } public function get data():ByteArray { return _data; } public function set data(value:ByteArray):void { _data = value; } } }
package client.net.packets { /** * @author KorDum */ public class SomePacket extends Packet { public static const SOME_COOMAND:uint = 0x0000; // дриугие константы private var _command:uint; private var _message:String; //--------------------------------------------------------------------------- // // CONSTRUCTOR // //--------------------------------------------------------------------------- public function SomePacket () { type = Packet.SOME_PACKET; } //--------------------------------------------------------------------------- // // PUBLIC STATIC METHODS // //--------------------------------------------------------------------------- // для формирования пакета из сырых байтов (когда пришли из сокета) public static function createByData(length:uint, data:PacketByteArray):SomePacket { var packet:SomePacket = new SomePacket (); packet.data = data; packet.length = length; packet.command = data.readCommand(); packet.message = data.readMessage(); return packet; } // для формирования пакета из команды (для отправки) public static function createByCommand(command:uint):SomePacket { var packet:SomePacket = new SomePacket (); var buffer:PacketByteArray = new PacketByteArray(); buffer.writeCommand(command); packet.data = buffer; packet.length = buffer.length; packet.command = command; return packet; } // для формирования пакета из команды и сообщения (для отправки) public static function createByCommandMessage(command:uint, message:String):SomePacket { var packet:SomePacket = new SomePacket (); var buffer:PacketByteArray = new PacketByteArray(); buffer.writeCommand(command); buffer.writeUTFBytes(message); packet.data = buffer; packet.length = buffer.length; packet.command = command; packet.message = message; return packet; } //--------------------------------------------------------------------------- // // PUBLIC ACCESSORS // //--------------------------------------------------------------------------- public function get command():uint { return _command; } public function set command(value:uint):void { _command = value; } public function get message():String { return _message; } public function set message(value:String):void { _message = value; } } }
Ведь и тут ничего сложного, правда?
Наконец-то я решил осветить PacketByteArray! Это надстройка на ByteArray, весьма и весьма удобная. Ведь если изменится протокольная сигнатура в плане того, что команда вдруг станет не short, а int, все легко правится в одном единственном месте. Пожалуй, то, что в AS3 нет никаких целочисленный типов, окромя (u)int, здесь играет очень даже на руку.
package client.net.packets { import flash.utils.ByteArray; /** * @author KorDum */ public class PacketByteArray extends ByteArray { //--------------------------------------------------------------------------- // // CONSTRUCTOR // //--------------------------------------------------------------------------- public function PacketByteArray() { } //--------------------------------------------------------------------------- // // PUBLIC METHODS // //--------------------------------------------------------------------------- public function writeLength(value:uint):void { writeInt(value); } public function writeType(value:uint):void { writeByte(value); } public function writeCommand(value:uint):void { writeShort(value); } public function writeIdRoom(value:uint):void { writeInt(value); } public function readLength():uint { return readInt(); } public function readType():uint { return readByte(); } public function readCommand():uint { return readShort(); } public function readIdRoom():uint { return readInt(); } public function readMessage():String { if (!bytesAvailable) { return null; } return readUTFBytes(bytesAvailable); } } }
Теперь вернемся к методу writePacket. Он принимает в себя пакет (ему без разницы, какой пакет именно, собираются в сырые данные они все совершенно одинаково). И пример использования:
Вот и все =)
Я очень советую почитать комментарии ко всем частям. Там на самом деле дофига полезного.
Часть 1. Часть 2.
Всего комментариев 30
Комментарии
![]() ![]() |
|
Предложите красивый и хороший вариант, я с радостью им воспользуюсь. 20 листов кода ведь никто печатать не собирается, а функцию и свернуть можно.
|
![]() ![]() |
|
Словарь да, уже лучше. То же количество строк, но уже без break'ов.
|
![]() ![]() |
|
в java можно извернуться вот так:
https://github.com/ramshteks/touchpo...ientLogic.java Зависимость от : https://github.com/ramshteks/javabyc.../Strategy.java |
![]() ![]() |
|
Ребята, - есть protoBuf, AMF, BSON
|
|
Обновил(-а) Котяра 14.07.2012 в 11:51
|
![]() ![]() |
|
это все те же яйца, только вид в профиль
|
![]() ![]() |
|
Цитата:
Сообщение от КорДум;
И пакет переписал еще. Вот думаю, доделывать статью или комментарии сгодятся?
![]() |
![]() ![]() |
|
Furinax, окей, в ближайшее время внесу правки.
incoob, как я уже сказал, в серверных делах опыта маловато (и конечно же, как всегда, такие "нубы", как я ломятся писать статьи). Не понял, причем здесь конкретно netty. На netty декодер уже написан: @Override protected Object decode(ChannelHandlerContext context, Channel channel, ChannelBuffer channelBuffer, DecoderStates state) throws Exception { if (state == DecoderStates.LENGTH) { _length = channelBuffer.readInt(); checkpoint(DecoderStates.TYPE); } else if (state == DecoderStates.TYPE) { _type = channelBuffer.readByte(); checkpoint(DecoderStates.MESSAGE); } else if (state == DecoderStates.MESSAGE) { ChannelBuffer buffer = channelBuffer.readBytes(_length); checkpoint(DecoderStates.LENGTH); return PacketFactory.create(_length, _type, buffer.array()); } return null; } Дальше пакет собирается уже окончательно (режутся байты в сообщении, вытаскиваются команды) так же удобно, как посоветовал ramshteks. Не вижу неудобств и сложностей. Сменится размерность значащих кусков в сообщении — правим только в одном месте, автоматом "подхватывается" во всех других. Или я Вас не понял совершенно? Разве что я не врубился, как прикрутить мой допиленный ChannelBuffer в этот метод так, чтобы длину и тип считывать моими методами (обертки вокруг readInt и readByte). А то ведь сменится протокол, придется менять в двух местах, а не в одном. |
|
Обновил(-а) КорДум 15.07.2012 в 20:11
|
![]() ![]() |
|
И тут дописал-переписал.
Котяра, я разбавил учебный тон статьи своими неформальными комментариями ) |
![]() ![]() |
|
Цитата:
Как дальше упростить использование пока не придумывал. Навскидку, можно при генерации кода генерировать и номер команды.
Т.е. для нового .proto класса мне надо было сгенерить новый AS класс, прописать его в registerClassByAlias и реализовать метод а-ля execute (в примере это changeModel) Покороче твоего варианта. |
![]() ![]() |
|
Ты имя класса передавал с каждым сообщением, а имя может быть очень длинным
![]() Я передаю не строку, а целочисленную константу (id команды). Вот тут и получается разница - в твоем случае константа просто не нужна. |
|
Обновил(-а) incoob 18.07.2012 в 21:15
|
![]() ![]() |
|
А где я передаю строку?
|
![]() ![]() |
|
А, это Котяре =)
|
Последние записи от КорДум
- Basic authentication и GET/POST запросы (20.03.2013)
- SOAP и Flash (19.12.2012)
- Бинарные сокеты в AS3. Часть 3 (13.07.2012)
- Бинарные сокеты в AS3. Часть 2 (13.07.2012)
- Бинарные сокеты в AS3. Часть 1 (13.07.2012)