1.数据包头
package com.net.tcp
{
/**
* 数据包头
**/
public class DataHead
{
/**包头长度*/
public static const DATA_HEAD_LEN:uint = 4;
private var _len:uint;
public function DataHead()
{
}
public function get len():uint
{
return _len;
}
public function set len(value:uint):void
{
_len = value;
}
}
}
2.数据内容
package com.net.tcp
{
import flash.utils.ByteArray;
import flash.utils.Proxy;
import flash.utils.flash_proxy;
/**
* 数据内容
**/
public class DataContent extends ByteArray
{
public function rewind():void{
this.position = 0;
}
}
}
3.完整数据包
package com.net.tcp
{
import avmplus.getQualifiedClassName;
import com.commons.utils.ClassUtils;
import com.commons.utils.Map;
import flash.utils.describeType;
import flash.utils.getDefinitionByName;
/**
* 通信数据包
**/
public class DataPack
{
private var _head:DataHead;
private var _content:DataContent;
public function DataPack(content:DataContent = null, head:DataHead = null)
{
if(head == null){
_head = new DataHead();
}else{
_head = head;
}
if(content == null){
this.content = new DataContent();
}else{
this.content = content;
}
}
public function get head():DataHead
{
return _head;
}
public function set content(value:DataContent):void
{
_content = value;
_content.rewind();
_head.len = _content.bytesAvailable;
}
public function get content():DataContent
{
return _content;
}
private function readType():int{
return _content.readShort();
}
private function readValue(t:int = -1):*{
var len:int = 0;
var index:int = 0;
var type:int = t == DataType.TYPE_ALL ? this.readType() : t;
var f:String = null;
var fv:Object = null;
switch(type){
case DataType.TYPE_NULL:
return null;
case DataType.TYPE_BYTE:
return _content.readByte();
case DataType.TYPE_SHORT:
return _content.readShort();
case DataType.TYPE_INT:
return _content.readInt();
case DataType.TYPE_DOUBLE:
return _content.readDouble();
case DataType.TYPE_BOOL:
return _content.readBoolean();
case DataType.TYPE_STRING:
len = _content.readInt();
return _content.readUTFBytes(len);
case DataType.TYPE_STREAM_OBJECT:
var so:StreamObject = StreamObject(StreamObjectManager.getObjectByClassName(this.readValue(DataType.TYPE_STRING)));
so.decode(this);
return so;
case DataType.TYPE_ARRAY:
len = _content.readInt();
var array:Array = new Array();
if(len > 0){
var type1:int = this.readType();
if(type1 == DataType.TYPE_STREAM_OBJECT){
var name:String = this.readValue(DataType.TYPE_STRING);
for(index = 0; index < len; index++){
var item:StreamObject = StreamObject(StreamObjectManager.getObjectByClassName(name));
item.decode(this);
array.push(item);
}
}else{
for(index = 0; index < len; index++){
array.push(this.readValue(type1));
}
}
}
return array;
case DataType.TYPE_MAP:
len = _content.readInt();
var map:Map = new Map();
if(len > 0){
for(index = 0; index < len; index++){
f = this.readValue(DataType.TYPE_STRING);
fv = this.readValue();
map.put(f, fv);
}
}
return map;
case DataType.TYPE_OBJECT:
len = _content.readInt();
var object:Object = new Object();
if(len > 0){
for(index = 0; index < len; index++){
f = this.readValue(DataType.TYPE_STRING);
fv = this.readValue();
object[f] = fv;
}
}
return object;
default:
throw new Error("找不到解析类型...");
}
}
public function readObject(t:int = -1):*{
return this.readValue(t);
}
private function writeType(type:int):void{
this.writeValue(type, false, [DataType.TYPE_SHORT]);
}
private function writeValue(value:Object, writeType:Boolean = false, types:Array = null):void{
if(value == null){
if(writeType){
this.writeType(DataType.TYPE_NULL);
}
}else if(value is Number){
if(writeType){
this.writeType(types[0]);
}
var number:Number = Number(value);
if(isNaN(number)){
number = 0;
}
switch(types[0]){
case DataType.TYPE_BYTE:
_content.writeByte(number);
break;
case DataType.TYPE_SHORT:
_content.writeShort(number);
break;
case DataType.TYPE_INT:
_content.writeInt(number);
break;
case DataType.TYPE_DOUBLE:
_content.writeDouble(number);
break;
}
}else if(value is Boolean){
if(writeType){
this.writeType(DataType.TYPE_BOOL);
}
if(value)
this.writeValue(1, false, [DataType.TYPE_BYTE]);
else
this.writeValue(0, false, [DataType.TYPE_BYTE]);
}else if(value is String){
if(writeType){
this.writeType(DataType.TYPE_STRING);
}
var begin:uint = _content.position;
this.writeValue(0, false, [DataType.TYPE_INT]);
_content.writeUTFBytes(String(value));
var end:uint = _content.position;
_content.position = begin;
this.writeValue(end - begin - 4, false, [DataType.TYPE_INT]);
_content.position = end;
}else if(value is StreamObject){
if(writeType){
this.writeType(DataType.TYPE_STREAM_OBJECT);
this.writeValue(ClassUtils.getSimpleNameByObject(value), false, [DataType.TYPE_STRING]);
}
var so : StreamObject = value as StreamObject;
so.encode(this);
}else if(value is Array){
if(writeType){
this.writeType(DataType.TYPE_ARRAY);
}
var array:Array = value as Array;
var len:int = array.length;
this.writeValue(len, false, [DataType.TYPE_INT]);
if(len > 0){
if(value[0] is StreamObject){
this.writeType(DataType.TYPE_STREAM_OBJECT);
this.writeValue(ClassUtils.getSimpleNameByObject(value), false, [DataType.TYPE_STRING]);
}else{
if(types.length >= 1){
this.writeType(types[1]);
}else{
if(value[0] is Number){
this.writeType(DataType.TYPE_DOUBLE);
}else if(value[0] is Array){
this.writeType(DataType.TYPE_ARRAY);
}else{
this.writeType(DataType.TYPE_OBJECT);
}
}
}
var index:int = 0;
var types1:Array = types.slice(1, types.length);
for(index = 0; index < len; index++){
this.writeValue(value[index], false, types1);
}
}
}else if(value is Map){
if(writeType){
this.writeType(DataType.TYPE_MAP);
}
var map:Map = value as Map;
this.writeValue(map.keys().length, false, [DataType.TYPE_INT]);
var v:Object = null;
for each(var key:Object in map.keys()){
v = map.get(key);
this.writeValue(String(key), false, [DataType.TYPE_STRING]);
this.writeValue(v, true, [DataType.getNumberTypeByObject(v)]);
}
}else{
if(writeType){
this.writeType(DataType.TYPE_OBJECT);
}
var size:int = 0;
for(var f:String in value){
size++;
}
this.writeValue(size, false, [DataType.TYPE_INT]);
for(var name:String in value){
this.writeValue(name, false, [DataType.TYPE_STRING]);
this.writeValue(value[name], true, [DataType.getNumberTypeByObject(value[name])]);
}
}
}
private function validateObjectType(value:Object, type:int):Boolean{
if(DataType.isNumberType(type)){
if(!DataType.isNumberType(DataType.getNumberTypeByObject(value))){
return false;
}
return true;
}
return true;
}
public function writeObject(value:Object, ...types):void{
if(!this.validateObjectType(value, types[0])){
throw new Error("解析对象类型和传入的对象类型不匹配...");
}
this.writeValue(value, true, types);
}
public function rewind():void{
this.content.rewind();
this.head.len = this.content.bytesAvailable;
}
}
}