问题:
服务端Mina 前台接收Flex
参照的原型为http://www.klstudio.com/post/202.html
<[Socket
+AMF3]给合Flash的Socket和AMF3来尝试开发
web游戏
>
经过个人调试 分别在服务端和客户端收发消息时进行长度处理
但是在服务端大量发送数据
时,还是会发生客户端粘包的状况,导致发生错误,而且也比较频繁。
求服务端与客户端的收发代码
段。要实用的。
(最好是经过一定压力测试的。或者发上来我压一下。)
补充说明一次我打断点跟踪到的情况:
客户端接收到信息:
获取了长度:长度为34字节 查看socket里面也确实还有34字节的内容
但是这时候就读取object就会出现异常
flex
.messaging.io.UnknownTypeException: Unknown AMF type '120'
120这个就是34字节当中的第一个的内容 还有其他的比如 -124 之类的等等。
解答:
这个基本是socket编程都会遇到的经典问题
amf本身是一种2进制封装,连发时接收方可能会因为数据堆积在一起而分不清包的头尾,造成映射错误。
解决办法就是在发包前对amf进行简单封包,因为amf本身就是2进制格式,那么只需要在其之前写入amf长度(即正文长度),接收方,先读取包头的长度,再固定取出其后的正文。取完正文,再取包头,依次取完。
每个发出的包,结构为
struct
{
DWORD Data_LEN //包长
CHAR[..] //内容
}
理论说完,就给出关键代码,相信认真研究过socket的一看就知:
as3 ---> Server 发送部分
public function send(obj:Object)
{
var objByte:ByteArray = new ByteArray();
objByte.writeObject(obj);
// objByte.compress(); //压缩,可以省略
var msgByte:ByteArray = new ByteArray();
msgByte.writeInt(objByte.length);
msgByte.writeBytes(objByte, 0, objByte.length);
sk.writeBytes(msgByte);
sk.flush();
}
server --> as3 接收部分
//一接受到数据就尝试读
private function onSkData(e:ProgressEvent):void
{
this.readData();
}
private function readData():void
{
//如果还没读过头部则读一次。
if (!this.isReadHead && this.sk.bytesAvailable > 4)
{
var lenByte:ByteArray = new ByteArray();
sk.readBytes(lenByte, 0, 4);
this.msgLen = lenByte.readInt();
//trace("新的消息长度:" + this.msgLen);
this.isReadHead = true;
}
//如果读了头部,并且当前可读长度大于等于消息长度,则开始读取
if (isReadHead && this.sk.bytesAvailable >= this.msgLen)
{
var objByte:ByteArray = new ByteArray();
sk.readBytes(objByte, 0, this.msgLen);
this.isReadHead = false;
//objByte.uncompress();
var obj:Object = objByte.readObject();
this.readMsg(obj); //读完了,可以去解释了
}
//如果是读过头,则如果当前消息大于消息长度则再次调用读取,否则则判断是否可读头部
this.sk.bytesAvailable > 0 && this.readData();
}
至于server端,其原理是一样的,都是读的时候先读头,发的时候也是先发个头。
补充server端代码(C#,解码类为FluorineFx,仅供参考思路)
server -> as3 发送
public void send(object obj)
{
try
{
ByteArray objByte = new ByteArray();
objByte.WriteObject(obj);
// objByte.Compress();
byte[] objBuff = new byte[objByte.Length];
objByte.Position = 0;
objByte.ReadBytes(objBuff, (uint)0, (uint)objBuff.Length);
ByteArray msgByte = new ByteArray();
msgByte.WriteInt(objBuff.Length);
msgByte.WriteBytes(objBuff, 0, objBuff.Length);
byte[] msgBuff = new byte[msgByte.Length];
msgByte.Position = 0;
msgByte.ReadBytes(msgBuff, (uint)0, (uint)msgBuff.Length);
//发送
this.ng.sk.BeginSend(msgBuff, 0, msgBuff.Length, SocketFlags.None, onSendOver, this.ng);
}
catch
{
Core.mainForm.addLog("发送失败");
}
}
as3 -> server 接受
//接收完的回调
private void receOver(IAsyncResult ar)
{
NetGate ng = (NetGate)ar.AsyncState;
int size = ng.sk.EndReceive(ar);
// Core.mainForm.addLog("接受到总长度:" + size);
int ind = 0;
if (size > 0)
{
while (size > 0)
{
//读消息头
MemoryStream lenMs = new MemoryStream(ng.buff, ind, 4);
ByteArray lenByte = new ByteArray(lenMs);
Int32 len = lenByte.ReadInt();
// Core.mainForm.addLog("消息长度:" + len.ToString());
if (len == 0) { break; }
//根据头长度取内容
MemoryStream ms = new MemoryStream(ng.buff, ind + 4, len);
ByteArray ba = new ByteArray(ms);
// ba.Uncompress();
object obj = ba.ReadObject();
this.readMsg(obj);
ind += (len + 4);
size -= (len + 4);
}
this.ng.buff.Initialize();
ng.sk.BeginReceive(this.ng.buff, 0, this.ng.buffSize, SocketFlags.None, this.onReceOver, this.ng);
}
else
{
ng.sk.Close();
this.offLine();
}
}
分享到:
相关推荐
NULL 博文链接:https://leopard0825.iteye.com/blog/644028
自己写的flash webgame 搭建的java 后台 解决了安全沙箱问题,可以进行聊天,和后台java函数的请求及响应。amf3 编码。
NULL 博文链接:https://sjkgxf7191.iteye.com/blog/572828
之前测试解析amf3协议数据进行树化便于观察的,解析的有可能不是很完美,正常用来观察里面的数据没什么问题
AMF3 C++ 源码 修改版 支持序列化和对象化的AMF3解析
amf3_spec amf3_spec amf3_spec amf3_spamf3_specec
AMF3 C++ AMF3 C++ 源码库码库
AMF3协议中文版定义.pdf
amf3_spec_05_05_08.pdf amf3_spec_05_05_08.pdf amf3_spec_05_05_08.pdf
一个用C++编写的,amf3协议解析模块,可以实现flash通信协议的解析
amf3 的格式说明,英文版,做rtmp协议或者做与flash数据交互服务器端必备的参考
PHP的amfext扩展,pecl.php.net上提供的0.9.2无法兼容php5.4+的版本,这个资源能确保amfext扩展在php5.4+的环境下编译成功。 本人分别在php5.4/5.5的生产环境中使用,一切正常,各位可以放心使用。
Action Message Format AMF3中英文对照 本人翻译 Abstract Action Message Format AMF is a compact binary format that is used to serialize ActionScript object graphs Once serialized an AMF encoded object ...
支持AS3的ByteArray序列化对象的AMF格式编码、解码( readObject、writeObject )。 支持AS3的ByteArray的compress、uncompress压缩算法:DEFLATE、LZIB、LZMA。 支持直接修改AS3的ByteArray字节流内编码的对象。 ...
amf0 原版文档 完整版
Adobe Flash AMF3 specification for flash player 9 and above serialization and communication.
易语言amf解析构造源码,amf解析构造,分析amf,取短整数_字节集,时间到双精度,到时间_双精度,取整数_字节集,integer_字节集,取双精度_字节集,amf3型数据,十六进制转字节集,分析数据段,解析amf数据,解析amf3数据,Utf8转...
这实现了几乎所有AMF3功能,但对于长尾负载而言,性能至少提高了一个数量级。 作为“项目的一部分而编写。 安装: npm install node_amf_cc 用法: var amfcc = require('node_amf_cc'); var encoded = amfcc....
AMF1.0(AMP).zip 代码