在最近参与开发的adobe air项目中,前后端的通信协议从XML、JSON再到protobuf,最后选择protobuf原因,主要是前后端维护protobuf协议就行了,同时还可以利用IDE做一些编译检查。目前我能找到的protobuf as3开源库,都存在一些问题:不支持嵌套类,生成代码无法编译等等。于是花了一点时间,参考google protobuf相关说明,编写protobuf-as3以及protoc-as3,用于支持运行时及代码生成,https://github.com/zhongfq/protobuf-as3

  protobuf-as3库只支持proto3格式,proto3列出的数据类型基本都支持。

  以下proto文件将生成5个as3类:Token.as、Token$Type.as、TokenBindingResponseCode.as、TokenBindingRequest.as、TokenBindingResponse.as。我们以‘$’作为分隔符以实现protobuf类的嵌套。

syntax = "proto3";
package user.token; message Token {
enum Type {
NONE = ;
QQ = ;
WEIBO = ;
WECHAT = ;
} Type type = ;
string value = ;
} enum TokenBindingResponseCode {
ERROR = ;
OK = ;
EXIST = ;
} message TokenBindingRequest {
Token token = ;
} message TokenBindingResponse {
TokenBindingResponseCode responseCode = ;
Token token = ;
}
var token:Token = new Token();
token.type = Token$Type.QQ;
token.value = "xxxxxx"; var req:TokenBindingRequest = new TokenBindingRequest();
req.token = token;

protobuf数据不包含任何的元数据,所以对于一段数据而言,你是不能够区别这段数据是属于哪一条协议的,因此对于前后端的交互,我引入12字节的头部(length、session、type)。

package network {

import flash.utils.ByteArray;

internal class Packet {
private var _session:int;
private var _type:int;
private var _data:ByteArray; public function Packet(session:int, type:int, data:ByteArray) {
_session = session;
_type = type;
_data = data;
_data.position = 0;
} public function get session():int {
return _session;
} public function get type():int {
return _type;
} public function get data():ByteArray {
return _data;
}
}
}
package network {

import flash.net.Socket;
import flash.utils.ByteArray;
import flash.utils.Endian; internal class PacketBuffer {
//length + session + type
private static const HEADER_LENGTH:int = 12;
private var _length:int = 0;
private var _position:int = 0;
private var _packet:Packet = null; public function PacketBuffer() {
} public function pack(socket:Socket):Packet {
// 消息长度至少为12, length + session + type
if (socket.bytesAvailable <= 0 || (_length == 0 && socket.bytesAvailable < HEADER_LENGTH)) {
return null;
} socket.endian = Endian.BIG_ENDIAN; if (_length == 0) {
_length = socket.readInt(); // valid packet: length + session + type >= 12
if (_length < HEADER_LENGTH) {
socket.close();
return null;
} var session:int = socket.readInt();
var type:int = socket.readInt(); _position = 0;
_packet = new Packet(session, type, new ByteArray());
} if (socket.bytesAvailable > 0 || _length == HEADER_LENGTH) {
var len:int = Math.min(_length - HEADER_LENGTH - _position, socket.bytesAvailable);
socket.readBytes(_packet.data, _position, len);
_position += len; if (_position == _length - HEADER_LENGTH) {
var ret:Packet = _packet; _packet = null;
_position = 0;
_length = 0; return ret;
}
} return null;
}
}
}
syntax = "proto3";

enum CommandCode {
// gateway
GATEWAY = 0x0000; // login
SIGN_IN = 0x0100;
CHECK_ACCOUNT = 0x0101;
SIGN_UP = 0x0102;
QUICK_ENROLL = 0x0103; // user
USER_MODIFIER = 0x0200;
TOKEN_BINDING = 0x0201;
USER_STAT = 0x0202;
USER_AVATAR = 0x0203;
}

CommandCode作为数据包的类型标识,用于上面所说头部中的类型段。

对于发送一个数据包,方式如下:

private function sendPacket(packet:Packet):void {
// length + session + type
_socket.endian = Endian.BIG_ENDIAN;
_socket.writeInt(packet.data.length + 12);
_socket.writeInt(packet.session);
_socket.writeInt(packet.type);
_socket.writeBytes(packet.data);
_socket.flush();
}

对于接收数据包,方式如下:

private function socketDataHandler(event:ProgressEvent):void {
var packet:Packet;
while ((packet = _packetBuffer.pack(_socket)) != null) {
dispatchPacket(packet);
}
}

session变量由服务器维护,服务器每发送一条用户数据,session就+1,前端断线重连时,发送session与服务作对比,如果一样,就是执行断线重连,如果不一样就强制走登录流程。

在as3中使用protobuf的更多相关文章

  1. 在Wcf中应用ProtoBuf替代默认的序列化器

    Google的ProtoBuf序列化器性能的牛逼已经有目共睹了,可以把它应用到Socket通讯,队列,Wcf中,身为dotnet程序员一边期待着不久后Grpc对dotnet core的支持更期待着Wc ...

  2. webapi 中使用 protobuf

    相比json来说,好处是速度更快,带宽占用更小.其效果大致等于json+Gzip. 在webapi中使用protobuf的方法为: 引用nuget包 Install-Package protobuf- ...

  3. as3中的多线程

    从fp11.4开始支持worker技术, 即as3中的线程概念, 到了fp11.5, flascc中开始支持pthread家族来创建线程. 总的来说, as3中有两种创建线程的方法: 1.直接在as3 ...

  4. 在网络通讯中应用Protobuf

    在网络通讯中应用Protobuf Protobuf的设计非常适用于在网络通讯中的数据载体,它序列化出来的数据量少再加上以K-V的方式来存储数据,对消息的版本兼容性非常强:还有一个比较大的优点就是有着很 ...

  5. AS3中释放优化的几条常识

    as3中垃圾和堆弃物如不及时清理,会造成进程的速度方面授予限制,下面讲几点关于释放优化的几条内容. 被删除对象在外部的所有引用一定要被删除干净才能被系统当成垃圾回收处理掉: 父对象内部的子对象被外部其 ...

  6. 怎样在Spark、Flink应用中使用Protobuf 3的包

    如果在在Spark.Flink应用中使用Protobuf 3的包,因为Spark默认使用的是2.5版本的包,提交任务时,可能会报如下异常: com.google.protobuf.CodedInput ...

  7. AS3中的单件(Singleton)模式

    单件(singleton)模式在c#中是最容易实现的模式,其主要用意就在于限制使用者用new来创建多个实例.但在as3中,构造函数必须是public的(语法本身要求的),而且也不能在构造函数中抛出异常 ...

  8. AS3中的getChildByName

    [转载的...............] 在AS3中,我们可以用getChildByName来获取一个元件,但是要注意返回的类型是DisplayObject,这样一旦我们的元件中有一些自定义的方法就不 ...

  9. 在lua环境中使用protobuf

    最近在cocos2dx的项目中,需要在LUA脚本层使用protobuf协议.官方已经推出了很多种语言的版本.但唯独LUA版本不全.于是开始研究protobuf在LUA下的实现,将完整的过程记录了下来, ...

随机推荐

  1. 6、Android之LayoutInflater.inflate()

    LayoutInflater.inflate()的作用就是将一个xml定义的布局文件实例化为view控件对象: 与findViewById区别: LayoutInflater.inflate是加载一个 ...

  2. web前端基础篇⑩

    1.960栅格式布局法屏幕分辨率为1024*768.采用接 main宽为960px的布局方式12列式:每格60px 间距20px 3 6 3版 三格式布局(最常用)16列式:每格40px 间距20px ...

  3. Power of Four(Difficulty: Easy)

    题目: Given an integer (signed 32 bits), write a function to check whether it is a power of 4. Example ...

  4. UGUI与DOtween的坑

    在使用ugui和dotween做动画时,如使用transform.DoMoveX,.DoLocalMoveX,.DoMove,.DoLocalMove等方法时,动画效果有可能是错误的,什么时候错误呢? ...

  5. UE4 WCF RestFul 服务器 读取JSON 数据并解析 简单实例

    Note:不知道为什么通过Txt读取的JsonString,如果TXT 不是ANSI编码的话,会报JsonArrayStringToUStruct  Unable to parse. bool UWg ...

  6. 关于TextView的setText()与Integer之间一个易犯的小错误

    [转载]原文:https://my.oschina.net/xybob/blog/59524 先上图: TextView的setText()函数的两个重载函数 因为TextView有两个不同的重载函数 ...

  7. select标签让文字垂直居中问题

    直接在select样式中添加:padding:npx 0; n的大小视select标签的高度而定.一般为8px左右.

  8. 如何消除inline-block元素间间距问题(转)

    一.现象描述    真正意义上的inline-block水平呈现的元素间,换行显示或空格分隔的情况下会有间距,很简单的个例子: <input /> <input type=" ...

  9. What Is Mathematics?

    What Is Mathematics? The National Council of Teachers of Mathematics (NCTM), the world's largest org ...

  10. WWDC 2014 发布会 Keynote 视频下载 3.6G 1080P地址

    我费尽九牛二虎之力,终于可以下载这个1080P高清的视频了,话说今天凌晨我是看的图文直播,现在终于有视频了,大家会不会很激动啊,好废话不多说,我把下载地址发给大家! 百度云:http://pan.ba ...