解释下erlang与flash通信细节

今天花了大半天时间给前端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次调用
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的分隔






你可能感兴趣的:(应用服务器,erlang,socket,Flash,网游)