Beetle在TCP通讯中使用AMF3协议和Flash通讯
Flash是现有网页中最流行的富客户端表现软件,所以组件支持Flash对象协议通讯也是非常有必要的事情.由于组件可以通过扩展协议分析器来兼容不同协议处理,所以可以通过使用FluorineFx就可以简单地实现基于AMF3的协议和Flash进行TCP通讯.如果有了解之前的Protobuf的扩展,那扩展AMF3也是很简单的事情.
定义协议格式
同样在交互前要明确一下协议的格式先,只有这样才可以方便的进行代码编写实现.
协议比较简分别消息总长度和内容,内容即是AMF3协议数据.
实现具体的分析器和消息适配器
协议制定后就可以进行分析器的实现,采用头4字节描述大小,所以分析器从HeadSizeOfPackage基础类派生下载重写相关方法即可;完整实现代码如下:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104public
class
AMF3Package:HeadSizeOfPackage
{
public
AMF3Package()
{
}
public
AMF3Package(TcpChannel channel)
:
base
(channel)
{
}
public
override
object
ReadCast(
object
message)
{
return
((MessageAdapter)message).Message;
}
public
override
object
WriteCast(
object
message)
{
MessageAdapter adapter =
new
MessageAdapter();
adapter.Message = message;
return
adapter;
}
protected
override
IMessage ReadMessageByType(BufferReader reader,
out
object
typeTag)
{
typeTag =
"MessageAdapter"
;
return
new
MessageAdapter();
}
protected
override
void
WriteMessageType(IMessage msg, BufferWriter writer)
{
}
public
override
void
MessageWrite(IMessage msg, BufferWriter writer)
{
msg.Save(writer);
}
public
override
IMessage MessageRead(BufferReader reader)
{
IMessage msg =
null
;
object
typeTag;
msg = ReadMessageByType(reader,
out
typeTag);
if
(msg ==
null
)
throw
NetTcpException.TypeNotFound(typeTag.ToString());
try
{
msg.Load(reader);
}
catch
(Exception e)
{
NetTcpException err = NetTcpException.ObjectLoadError(typeTag.ToString(), e);
throw
err;
}
return
msg;
}
class
MessageAdapter : IMessage
{
public
object
Message
{
get
;
set
;
}
public
void
Load(BufferReader reader)
{
ByteArraySegment segment = ByteSegment;
int
count = reader.ReadInt32();
reader.Read(count - 4, segment);
using
(System.IO.MemoryStream steram =
new
System.IO.MemoryStream(segment.Array, segment.Offset, segment.Count))
{
FluorineFx.AMF3.ByteArray ba =
new
FluorineFx.AMF3.ByteArray(steram);
ba.ObjectEncoding = FluorineFx.ObjectEncoding.AMF3;
Message = ba.ReadObject();
}
}
public
void
Save(BufferWriter writer)
{
ByteArraySegment segment = ByteSegment;
using
(System.IO.MemoryStream steram =
new
System.IO.MemoryStream(segment.Array))
{
FluorineFx.AMF3.ByteArray ba =
new
FluorineFx.AMF3.ByteArray(steram);
ba.ObjectEncoding = FluorineFx.ObjectEncoding.AMF3;
ba.WriteObject(Message);
segment.SetInfo(0, (
int
)steram.Position);
}
writer.Write(segment.Count + 4);
writer.Write(segment.Array, segment.Offset, segment.Count);
}
[ThreadStatic]
private
static
ByteArraySegment mByteSegment;
public
static
ByteArraySegment ByteSegment
{
get
{
if
(mByteSegment ==
null
)
mByteSegment =
new
ByteArraySegment(TcpUtils.DataPacketMaxLength);
return
mByteSegment;
}
}
}
}
Flash端协议分析器
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566package
{
import flash.net.Socket;
import flash.utils.ByteArray;
import flash.utils.Endian;
import mx.controls.Alert;
import mx.graphics.shaderClasses.ExclusionShader;
public
class
HeadSizeOfPackage
{
public
function HeadSizeOfPackage()
{
}
private
var
mMessageReceive:Function;
//消息接收回调函数
public
function
get
MessageReceive():Function
{
return
mMessageReceive;
}
public
function
set
MessageReceive(value:Function):
void
{
mMessageReceive = value;
}
private
var
mReader:ByteArray =
new
ByteArray();
private
var
mWriter:ByteArray =
new
ByteArray();
private
var
mSize:
int
=0;
//导入当前Socket接收的数据
public
function Import(socket:Socket):
void
{
socket.endian = Endian.LITTLE_ENDIAN;
while
(socket.bytesAvailable>0)
{
if
(mSize==0)
{
mSize= socket.readInt()-4;
mReader.clear();
}
if
(socket.bytesAvailable>= mSize)
{
socket.readBytes(mReader,mReader.length,mSize);
var
msg:Object = mReader.readObject();
if
(MessageReceive!=
null
)
MessageReceive(msg);
mSize=0;
}
else
{
mSize= mSize-socket.bytesAvailable;
socket.readBytes(mReader,mReader.length,socket.bytesAvailable);
}
}
}
//发磅封装的协议数据
public
function Send(message:Object,socket:Socket):
void
{
socket.endian = Endian.LITTLE_ENDIAN;
mWriter.clear();
mWriter.writeObject(message);
socket.writeInt(mWriter.length+4);
socket.writeBytes(mWriter,0,mWriter.length);
socket.flush();
}
}
}
运行效果
由于服务端的实现和之前的一样并没有什么改变只是更换一下泛型参,因此不再讲述具体实现了.以下是运行效果图.
下载代码:Code
总结
组件通过使用FluorineFx就可以简单实现和Flash进行AMF3的通讯,FluorineFx对AMF3的支持不错,不过应该组件似乎已经很久没有更新,在看他的源码时发现其性能还有很大的优化空间.如果使用FluorineFx的朋友对他的性能不感不理想,可以通过内存分析工具来分析一下大体可以找到慢的一些原因.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· 展开说说关于C#中ORM框架的用法!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?