AS3.0中使用Socket使用tcp服务器协议,它是一种流协议,不停的将分片传输给客户端,P作为流,发包是不会整包到达的,而是源源不断的。
它不同于UDP服务器协议,UDP作为数据包协议,整包到达。 如果要使用Socket接收数据我们必须使用ProgressEvent.SOCKET_DATA事件。这个事件在帮助文档中是这样描述的 ——在套接字接收到数据后调度。
而事实却并非如此,做过一次尝试,服务器发送了20000次数据而rogressEvent.SOCKET_DATA事件只产生了2000多次。
那么为什么说"服务器发送了20000次数据而rogressEvent.SOCKET_DATA事件只产生了2000多次",
因为flash socket使用的TCP/IP协议, 这个协议跟UDP不同,它不是以单个"包"的形式发送数据,它发送的是"流数据",所以即便你发来20000次数据(也就是你所想象的20000个包),TCP协议也是将它视作"流"发送.
换句话说,你的20000次数据,实际上只被分割成了2000多个"包"来发送,因此socket收到了2000多个包,,因此只产生了2000多次的事件.
另外,如果as3 的data事件函数正在执行的时候,比如在此函数中用while循环解码,此时有新的数据发送过来,data事件还会触发么?触发的话,正在执行的怎么办?原有数据还有么?
答案是会触发的,所以将socket数据read的时候,必须做一个循环 while,每到一个包刚好读取完成的时候(包头用一个整型记录完整包的长度。每次都先读取一个包长度,然后按照包长度读取指定长度的数据作为一个完整数 据包传递到到逻辑层),又继续读取下一个包,然后把解码后的每个包都放进一个数组里面依次读取。还有一点要注意的是 socket.bytesAvailable长度是每read一次就减去所读的长度,直至读取完毕,最后为0;此处的bytesAvailable如果重 新设置position为0,那该数组的bytesAvailable又是满的。
附一下代码进行研究:
view plaincopy to clipboardprint?
private function Net_Data(evt:ProgressEvent):void
{
var ba:ByteArray = new ByteArray();//创建一个
socket.readBytes(ba, 0, evt.bytesTotal); //服务器一次性发送的总共的数据,可能是几个包,也可能是几个半包
packetBuffer.push(ba); //把ba放入缓冲区,其实就是把ba放入packetBuffer类中的一个ByteArray对象里
var packets:Array = packetBuffer.getPackets(); //这里就是在进行解码(包含循环)
for each(var packet:MsgPacket in packets)
{
dispatch(packet); //对解码后的数据进行处理,可以说是直接使用、赋值
}
}
private function Net_Data(evt:ProgressEvent):void { var ba:ByteArray = new ByteArray();//创建一个 socket.readBytes(ba, 0, evt.bytesTotal); //服务器一次性发送的总共的数据,可能是几个包,也可能是几个半包 packetBuffer.push(ba); //把ba放入缓冲区,其实就是把ba放入packetBuffer类中的一个ByteArray对象里 var packets:Array = packetBuffer.getPackets(); //这里就是在进行解码(包含循环) for each(var packet:MsgPacket in packets) { dispatch(packet); //对解码后的数据进行处理,可以说是直接使用、赋值 } } packetBuffer.as
view plaincopy to clipboardprint?
package org.green.server.data
{
import flash.utils.ByteArray; public class PacketBuffer
{
private var buf:ByteArray = new ByteArray();
private static const SPLIT:int = 21316;// "DS"
public function PacketBuffer()
{
}
public function push(ba:ByteArray):void
{
if(buf == null)
{
buf = ba;
}else
{
buf.position = buf.length;
buf.writeBytes(ba);
}
}
public function getPackets():Array
{
var ps:Array = [];
var ptr:uint = 0;
buf.position = ptr;
while(buf.bytesAvailable >= 2) //这里是说当可用数据大于包头时,一个包==包头(body的长度)+包体(body),也就是说包里如果一旦有数据就开始执行
{ //2其实是readShort()后,少了的2个字节,也就是body有数据的时候才开始解码
var len:uint = buf.readShort();
//不足一个包,这里完全有可能,当只读取完包头len,但是body却没有读取到末尾
if(buf.bytesAvailable < len)
{
var ba:ByteArray = MsgUtil.createByteArray();
buf.position = ptr;
ba.writeBytes(buf, 0, buf.bytesAvailable);
buf = ba;
//返回
return ps;
}
buf.position = 2;
var mb:ByteArray = new ByteArray();
buf.readBytes(mb, 0, len); //len为body的长度,将body的数据放入mb
mb.position = 0;
var msg:MsgPacket = MsgUtil.createMsgPacket(mb,magic);//这里在对body解码过程 略
buf.position=0;
ps.push(msg); //放入数组
//下一个包 while语句进行下一个循环
}
if(buf.bytesAvailable <= 0)buf = null;
return ps;
}
public function clear():void
{
buf=null;
}
}
} as3 socket test
package {
import flash.display.Sprite;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.events.ProgressEvent;
import flash.external.ExternalInterface;
import flash.net.Socket;
public class receiveData extends Sprite
{
public function receiveData()
{
trace(ProgressEvent.SOCKET_DATA);
socket.connect("127.0.0.1", 4300);
socket.addEventListener(ProgressEvent.SOCKET_DATA, onServerData,false,0,true);
socket.addEventListener(Event.CONNECT, connectHandler);
socket.addEventListener(Event.CLOSE, closeHandler);
socket.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
}
private var socket:Socket=new Socket();
private var msg:String = "";
private function onServerData(event:ProgressEvent):void{
if(socket.bytesAvailable){
msg = socket.readUTFBytes(socket.bytesAvailable);
trace(msg);
ExternalInterface.call("window.jsFunc", msg);
}
}
private function connectHandler(event:Event):void{
trace("connected");
}
private function closeHandler(event:Event):void{
trace("closed");
clearHandler();
}
private function ioErrorHandler(event:IOErrorEvent):void{
//to do
clearHandler();
}
private function clearHandler():void{
socket.removeEventListener(ProgressEvent.SOCKET_DATA, connectHandler);
socket.removeEventListener(Event.CONNECT, connectHandler);
socket.removeEventListener(Event.CLOSE, closeHandler);
socket.removeEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
}
}
}

AS3: Socket 数据包 收 发的更多相关文章

  1. C# 实现的多线程异步Socket数据包接收器框架

    转载自Csdn : http://blog.csdn.net/jubao_liang/article/details/4005438 几天前在博问中看到一个C# Socket问题,就想到笔者2004年 ...

  2. Java nio socket与as3 socket(粘包解码)连接的应用实例

    对Java nio socket与as3 socket连接的简单应用 <ignore_js_op>Java nio socket与as3 socket连接的应用实例.rar (9.61 K ...

  3. Socket 数据包顺序的问题

    今天遇到一个问题,到现在还未查明原因,记录一下,留后续跟踪. 基于Netty的Socket通讯问题,Server在向Client发送数据时,假设数据原顺序为1,2,3,4...  但到了客户端顺序可能 ...

  4. 数据包从物理网卡流经 Open vSwitch 进入 OpenStack 云主机的流程

    目录 文章目录 目录 前言 数据包从物理网卡进入虚拟机的流程 物理网卡处理 如何将网卡收到的数据写入到内核内存? 中断下半部分软中断处理 数据包在内核态 OvS Bridge(Datapath)中的处 ...

  5. Tcp/Ip协议族简单解读及网络数据包/报/帧数据格式及封装及解包;

    http://www.creseek.cn/products-install/install_on_bsd_linux/ 中文检索 离线cloudera ecosystem components: h ...

  6. 数据包接收系列 — IP协议处理流程(二)

    本文主要内容:在接收数据包时,IP协议的处理流程. 内核版本:2.6.37 Author:zhangskd @ csdn blog 我们接着来看数据包如何发往本地的四层协议. ip_local_del ...

  7. Linux网络 - 数据包的接收过程【转】

    转自:https://segmentfault.com/a/1190000008836467 本文将介绍在Linux系统中,数据包是如何一步一步从网卡传到进程手中的. 如果英文没有问题,强烈建议阅读后 ...

  8. Linux 中的网络数据包捕获

    Linux 中的网络数据包捕获 Ashish Chaurasia, 工程师 简介: 本教程介绍了捕获和操纵数据包的不同机制.安全应用程序,如 VPN.防火墙和嗅探器,以及网络应用程序,如路由程序,都依 ...

  9. 基于TILE-GX实现快速数据包处理框架-netlib实现分析【转】

    最近在研究suricata源码,在匹配模式的时候,有tilegx mpipe mode,转载下文,了解一下. 原文地址:http://blog.csdn.net/lhl_blog/article/de ...

随机推荐

  1. 今日成长笔记2016-11-18 - 关于java开发

    好久没有写今日成长笔记了,要记得上一次写笔记还是2016-09-05,今天心血来潮,写一写最近发生在自己身上的事情,以后我要坚持每天写日记.我承认自己身上的确或多或少的存在不足,现在把它们抛出来,并记 ...

  2. LightOJ 1338 && 1387 - Setu && LightOJ 1433 && CodeForces 246B(水题)

    B - B Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu Submit Status P ...

  3. C,C#,C++中&&和||,&和|的联系和区别

    本文来自:http://www.cnblogs.com/GT_Andy/archive/2010/03/30/1921805.html 两者计算结果相同(针对各自的运算对象),只是性能上有差别而已. ...

  4. C#获取本机IP方法,获取本机局域网IP地址方法

    1. private void GetIP() { string hostName = Dns.GetHostName();//本机名 //System.Net.IPAddress[] address ...

  5. asp.net + Jquery 实现类似Gridview功能 (一)

    不知不觉2015年就过去一半了,由于过年前后公司人员陆续离职(这个...),项目忙不过来,从过年来上班就一直在忙,最近项目终于告一段落,开始步入正轨(不用天天赶项目了).所以最近才有时间写这个东西,可 ...

  6. Haproxy+PXC实现负载均衡

    软件负载均衡一般通过两种方式来实现:基于操作系统的软负载实现和基于第 三方应用的软负载实现.LVS就是基于Linux操作系统实现的一种软负载,HAProxy就是开源的并且基于第三应用实现的软负载.HA ...

  7. [汇编语言]-第五章[bx]和loop指令

    1- [bx]和内存单元的描述 [0]表示内存单元, 他的偏移地址为0 mov ax,[0] 将一个内存单元的内容送入到ax.这个内存单元的长度为2字节(字单元),存放一个字,偏移地址为0,段地址在d ...

  8. python核心编程-第四章-个人笔记

    1.所有的python对象都拥有三个特性: ①身份:每个对象都有唯一的身份标识自己,可用内建函数id()来得到.基本不会用到,不用太关心 >>> a = 2 >>> ...

  9. linux shell--算术运算

    求和: 方法一.使用命令替换法: #!/bin/bash read -p 'input number a...' numA read -p 'input number b...' numB #这里有两 ...

  10. Ajax日记

    简要讲Ajax 的内容归纳为博客. AJAX能且仅能从服务器上读取文件,我们使用ajax的时候分为以下几个步骤: 1.  创建ajax对象 2.  链接服务器 3.  发送请求 4.  接收返回值 下 ...