最近要写一个c++和flash通过tcp通信的程序, 遇到了不少的麻烦, 最后是解决了, 现把解决方法记录一下
需要解决的问题就是使用C++通过本地tcp连接向flash程序单向循环发送字符串, 遇到的问题就是在flash端接收的时候发现明明在C++端分好几次send的数据, 在flash一端的回调却只会调用一次。
转载自:http://cjmxp007.blog.163.com/blog/static/35473837201061054116916/
AS3.0
中使用Socket使用
tcp服务器协议,它是一种流协议,不停的将分片传输给客户端,作为流,发包是不会整包到达的,而是源源不断的。
它不同于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又是满的。
附一下代码进行研究:
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
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;
}
}
}
上文中使用的是一个缓存的技术解决了问题, 但是我不需要这么复杂, 最后, 我是这样解决问题的:
package
{
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.ProgressEvent;
import flash.net.Socket;
/**
* ...
* @author
*/
public class get_udp extends MovieClip
{
var RFIDSocket:Socket;
var receive_buffer:String="";
var comm_splitter:String = "\n";
public function get_udp()
{
init();
}
//var RFIDSocket:Socket;
function init():void
{
RFIDSocket = new Socket("localhost",16000);
RFIDSocket.addEventListener(ProgressEvent.SOCKET_DATA, socketData);
}
private function socketData(e:ProgressEvent):void
{
trace("收到的字节数"+RFIDSocket.bytesAvailable);
while (RFIDSocket.bytesAvailable)
{
// TODO: 进行优化, 一次读入多个字节, 检查是否含有回车, 然后进行截取
var temp_char:String = RFIDSocket.readUTFBytes(1);
// 如果读入的是通信分割, 则进行处理
if (temp_char == comm_splitter)
{
processKinectData(receive_buffer);
receive_buffer = "";
}else // 如果读入的是普通字符, 则存储
{
receive_buffer += temp_char;
}
}
}
private function processKinectData(data:String):void
{
trace("处理Kinect数据:" + data);
}
}
}
-------------------------EOF----------------------
分享到:
相关推荐
在Flash ActionScript3游戏开发中,Socket通信是实现客户端与服务器之间实时互动的重要技术手段。本文将深入探讨AS3中的Socket通信方式,特别是利用XMLSocket进行网络交互的细节。 首先,XMLSocket是AS3中用于低级...
而"socket"文件可能包含客户端代码或者是一个AS3项目文件,用于展示如何在Flash环境中建立Socket连接和发送/接收数据。 总结起来,这个主题涵盖了使用AS3的Socket进行客户端和服务端通信的基础知识,包括连接建立、...
这是一个关于使用Java Netty构建TCP服务器以及Flash ActionScript3开发客户端的游戏C/S程序源代码的项目。这个项目展示了如何在服务器端使用Java Netty框架来处理网络通信,以及在客户端利用ActionScript3来实现游戏...
AS3中的SOCKET技术是ActionScript 3.0中用于实现网络通信的一种方式,它允许客户端(通常是Flash应用程序)与服务器之间进行低级的、基于TCP/IP协议的双向数据传输。在AS3中,有两种主要的类用于实现SOCKET通信:...
在Flash Professional环境中打开FLA文件,我们可以看到相关的AS3代码和图形元素,这些代码可能是用来设置UDP连接,创建数据包,以及处理接收到的数据。 在AS3中实现UDP通信的步骤大致如下: 1. **初始化...
它接收由Flash发送过来的数据包,通常包含用户名和消息内容,然后将这些信息存储在数据库中,以便后续查询和回放。同时,PHP还负责处理其他用户发送过来的消息,将新消息推送给所有在线用户。这通常通过轮询...
- **事件驱动编程**:Socket通信通常是基于事件的,如数据接收、连接建立和关闭等,因此需要理解和使用事件处理模型。 - **错误处理和异常安全**:网络通信可能会遇到各种异常,如连接中断、数据包损坏等,需要妥善...
2. **ActionScript Socket类**:在Flex中,我们使用Flash的Socket类来建立与Java服务器的连接,通过open()方法指定服务器的IP地址和端口号,然后可以使用writeUTFBytes()和readUTF()等方法进行数据的读写。...
"Java Socket多人在线考试系统演示.swf"则可能是系统的一个动态演示,通过Flash动画的形式展示系统的主要功能和操作流程,帮助用户快速理解和上手。 总的来说,这个Java Socket多人在线考试系统涉及到的知识点包括...
2. **C# Socket类**:学习C#中的System.Net.Sockets命名空间,特别是Socket类的用法,如创建Socket实例,绑定端口,监听连接,接受客户端请求,以及发送和接收数据的方法。 3. **Flex与Socket通信**:在Flex中,...
2. **RTMP协议**:了解如何使用Flash Player与FMS通过RTMP协议进行数据交换,包括实时视频流、音频流和自定义数据包。 3. **AMF数据序列化**:AMF是一种高效的二进制数据格式,用于在Flash客户端和服务器之间交换...
- 编写Flash客户端:使用ActionScript编程,创建用户界面,实现Socket连接,发送和接收数据。 - 数据库设计:通常,聊天室会涉及用户信息、聊天记录等数据存储,因此需要设计合理的数据库结构。 - 安全性考虑:在...
1. **Socket或XMLSocket**:AS3提供了Socket和XMLSocket类用于实现客户端与服务器的双向通信,发送和接收游戏数据,如玩家动作、农场状态等。 2. **AMF(Action Message Format)**:通常用于Flash和服务器间的序列...
这些资源可能涵盖了如何创建Socket对象、绑定端口、连接远程服务器、发送和接收数据的详细步骤,以及如何通过ANE实现UDP广播的指南。 总之,AS3虽然在UDP广播方面有所限制,但结合其他语言和ANE技术,开发者依然...
软件部分则重点在于流媒体的处理,通过原始套接字(socket)进行数据包的发送和接收,以实现实时的视频传输和同步播放。FFmpeg库被用于处理和编码视频数据,以适应不同的格式和帧率需求。 文章详细描述了软件设计方案...
在RTMP协议中,每个数据包都有一个时间戳,用于同步发送和接收的数据。在长时间的直播过程中,如果时间戳超过了32位整数的最大值(即2^32-1),就会出现“扩展时间戳”问题,导致时间戳回绕,可能引发连接中断。 ...
“粘包”是指在网络传输过程中,多个数据包被错误地合并成一个数据包的现象,这会导致接收方无法正确解析数据。 - **问题描述**:在Java与Flex之间进行Socket通信时,如果发送的数据量较大或者网络环境不稳定,就有...
- `recvfrom()` 或 `read()` 函数:从网络接收UDP数据包,可以获取发送者的IP和端口信息。 6. LPC2400以太网控制器初始化: - 设置MAC地址:通过写入以太网控制器的特定寄存器,设置设备的物理MAC地址。 - IP...
wifi 协议栈实现细节 ...wifi 协议栈的实现细节涉及到 STA 模式、AP 模式、WPA 加密协议、编译、cw1200 驱动程序、lwip 信息处理结构图、lwip 启动时序、宏编译开关、内存池、接收数据包和 API 函数调用等多个方面。