解释下erlang与flash通信细节
程序员文章站
2024-01-12 18:57:52
...
今天花了大半天时间给前端flash同学解释TCP相关的原理和细节,并陪同一起写完了与erlang服务器的通信模块
flash socket一般2种,xmlSocket和 socket(binary),xmlsocket基本也是flash自己封装的啦
由于服务器是用的erlang,erlang已经提供了处理TCP协议,自动拆解包头的方法,也就是
{packet,N}这种用法了,那自然就用不着自己去做底层粘包,判断packet是否是一个完整应用层协议包的细节了
也就是说,服务器端和flash通信 格式是这样的:
------------------------
|N bytes header| body |
------------------------
我指定的是2个字节头
本来flash端也有一个简单的方法,可以自动拆解包头的,就是用readUTF方法,它实际对应的是这2次调用
但是实际上,它做的还不够(可能是erlang做的太好了),实际如果我们通信的字节数能保持在 1K 字节以内,那么是没问题的
但是如果通信的应用层协议数据包字节数超过了1K,就有问题了,实际是TCP MSS(Max Segment Size)的问题
flash也是封装成事件机制的,有数据可读会回调一个onSocketData方法,但是这时socket 接收缓冲区数据未必完全接收了一个应用层数据包,所以读到一个头后,按照头里指定的字节数去读取body,而缓冲区里没那么多数据,结果报错(这个是解释给前端同学的,做服务器端开发的就当我是废话好了)
flash端最终处理的代码是:
_tcp_short是一个全局变量,在递归中用于记录上一次读的包头大小
流程基本就是,flash当socket接收缓冲区里有数据时通知调用onSocketData,于是我们先读下包头,知道包体有多少字节,然后判断缓冲区剩下的字节是否够,不够就等待下次数据到达,够就读包头定义的那么多字节,然后继续递归判断(可以继续当我是废话)
本来一直是想避免让前端flash同学处理这样的低层协议细节的,所以如果没必要还是尽量减小应用层协议包的大小,这样直接readUTF,writeUTF就全搞定了,还是比较方便的
另外用flash的xmlSocket应该也不错的,那个是以\0作为应用层packet的分隔
flash socket一般2种,xmlSocket和 socket(binary),xmlsocket基本也是flash自己封装的啦
由于服务器是用的erlang,erlang已经提供了处理TCP协议,自动拆解包头的方法,也就是
{packet,N}这种用法了,那自然就用不着自己去做底层粘包,判断packet是否是一个完整应用层协议包的细节了
也就是说,服务器端和flash通信 格式是这样的:
------------------------
|N bytes header| body |
------------------------
我指定的是2个字节头
本来flash端也有一个简单的方法,可以自动拆解包头的,就是用readUTF方法,它实际对应的是这2次调用
header = socket.readShort(); //readShort在flash里是读2个字节 bytes = socket.readMultiByte(header,"utf-8")
但是实际上,它做的还不够(可能是erlang做的太好了),实际如果我们通信的字节数能保持在 1K 字节以内,那么是没问题的
但是如果通信的应用层协议数据包字节数超过了1K,就有问题了,实际是TCP MSS(Max Segment Size)的问题
flash也是封装成事件机制的,有数据可读会回调一个onSocketData方法,但是这时socket 接收缓冲区数据未必完全接收了一个应用层数据包,所以读到一个头后,按照头里指定的字节数去读取body,而缓冲区里没那么多数据,结果报错(这个是解释给前端同学的,做服务器端开发的就当我是废话好了)
flash端最终处理的代码是:
private function onSocketData(e:ProgressEvent):void { getTcpData(); } private function getTcpData():void { if(_tcp_short == 0){ _tcp_short = _socket.readShort(); } if(_socket.bytesAvailable >= _tcp_short ){ var s:String = _socket.readMultiByte(_tcp_short,"utf-8"); //recv packet,do your thing } _tcp_short = 0; if(_socket.bytesAvailable > 2) { getTcpData(); } }
_tcp_short是一个全局变量,在递归中用于记录上一次读的包头大小
流程基本就是,flash当socket接收缓冲区里有数据时通知调用onSocketData,于是我们先读下包头,知道包体有多少字节,然后判断缓冲区剩下的字节是否够,不够就等待下次数据到达,够就读包头定义的那么多字节,然后继续递归判断(可以继续当我是废话)
本来一直是想避免让前端flash同学处理这样的低层协议细节的,所以如果没必要还是尽量减小应用层协议包的大小,这样直接readUTF,writeUTF就全搞定了,还是比较方便的
另外用flash的xmlSocket应该也不错的,那个是以\0作为应用层packet的分隔
上一篇: rman配置及rman常用命令操作
推荐阅读