从头开始构建一个web即时通讯系统 - 客户端 - flash socket
2013-12-16 22:25
302 查看
flash中的socket
socket的构造实例化一个socket对象,只需要一行代码:
static var socket = new flash.net.Socket();
主动方法和被动方法
而剩下的工作便是把这个对象包装成合适接口供javascript调用了。这时候主要有两类方法,一类是主动性方法,由客户端直接发起的便是主动方法,比如connect、send就是主动方法。另一类是被动方法,也就是服务器端发起,然后在客户端触发事件,并被调用的回调方法,比如connected、receive就是被动方法。
主动方法和被动方法直接决定了代码的结构,决定了javascript和flash的互操作方式。
事件时序
我们从事件时序上来看一下flash中socket的可能的一个过程:
flash加载完毕
我们先注册一个回调,在flash加载完毕的时候,获得一个通知,以便为下面的连接做一些设置和准备。flash.external.ExternalInterface.call("setTimeout", jsScope + "loaded()");
建立一个socket连接
接着我们便使用下面的方法来建立一个socket连接static function connect(host : String, port : String) {
trace("Connecting to socket server at " + host + ":" + port);
socket.connect(host, Std.parseInt(port));
}
这里的两个形参:host为ip或者域名,port为通讯的端口。trace为输入到flash控制台的方法。
flash socket在端口上是有限制的,仅被允许访问4502-4534这个网段里的端口。
flash socket在执行socket.connect(host, Std.parseInt(port))时,无论如何,会先访问843端口,如果843端口被监听,并且在连接上后接收到一个policy-file.xml的话,才会断开与843端口的连接,并与调用方法时指定的端口连接。
如果flash没有正常得到这个policy-file.xml的话,从调用方法时指定的端口连接时刚连接上便获得这个policy-file.xml也是可以的。如果这两种情况下都没有获得policy-file.xml,那么通讯是不能继续的。这是flash特有的安全机制。
关于这个安全机制,以及提供这个policy-file.xml服务器程序policyserver,我会在稍后的教程里详细介绍。
连接失败
如果flash没有顺利连接上服务器,或者超时,我们可以注册一个回调来获得连接失败的通知,已准备重连。socket.addEventListener(flash.events.SecurityErrorEvent.SECURITY_ERROR, function(e) : Void {
trace("SECURITY ERROR : " + e.text);
flash.external.ExternalInterface.call("setTimeout", jsScope + "securityError('" +e.text+ "')", 0);
}
);
连接成功
如果顺利连接上了,这时候,我们可以通过下面的代码来注册一个回调,得到连接状态更新的通知。socket.addEventListener(flash.events.Event.CONNECT, function(e) : Void {
trace("Connected to server");
flash.external.ExternalInterface.call("setTimeout", jsScope + "connected()", 0);
}
);
发送消息
下面我们便可以从flash发送消息给服务器了static function send(msg) {
if (socket.connected) {
trace("Writing '" + msg + "' to server");
//socket.writeMultiByte(msg,"gb2312");
socket.writeUTFBytes(msg);
socket.flush();
} else {
trace("Cannot write to server because there is no connection!");
}
}
我们可以看到,这段代码里,我注释掉了socket.writeMultiByte(msg,"gb2312");此句代码。从字面意思上也可以了解,这里是使用了"gb2312"的编码来发送消息。
flash socket提供了丰富的方法,在以后的教程里,我会详细描述flash.net.Socket的每一个方法。
获取消息
如果服务器发送消息给客户端,我们也可注册一个回调来获取消息的内容socket.addEventListener(flash.events.ProgressEvent.SOCKET_DATA, function(e) : Void {
//var msg = socket.readMultiByte(socket.bytesAvailable,"gb2312");
var msg = socket.readUTFBytes(socket.bytesAvailable);
trace("Received : " + msg );
flash.external.ExternalInterface.call("setTimeout", jsScope + "receive('" + msg + "')", 0);
}
);
这里和发送消息类似,我们可以使用不同的编码标准来解码我们获得的字节流。
关闭连接
在完成通讯以后,如果我们需要关闭这个socket连接的话,可以使用下面的主动方法。static function close() {
if (socket.connected) {
trace("Closing current connection");
socket.close();
} else {
trace("Cannot disconnect to server because there is no connection!");
}
}
连接断开
在socket连接断开以后,我们可以注册一个回调来获得通知socket.addEventListener(flash.events.Event.CLOSE, function(e) : Void {
trace("Disconnected from server");
flash.external.ExternalInterface.call("setTimeout", jsScope + "disconnected()", 0);
}
);
IO错误
在通信过程中,如果有错误发生的话,我们可以这样来获得通知socket.addEventListener(flash.events.IOErrorEvent.IO_ERROR, function(e) : Void {
trace("IOERROR : " + e.text);
flash.external.ExternalInterface.call("setTimeout", jsScope + "ioError('" + e.text + "')" ,0);
}
);
完整的代码
//SocketBridge.hx
class SocketBridge {
static var socket = new flash.net.Socket();
static var jsScope;
static function main() {
if (flash.external.ExternalInterface.available) {
jsScope = flash.Lib.current.loaderInfo.parameters.scope;
if (jsScope == null) {
jsScope = "";
} else {
jsScope += ".";
}
/* Calls the javascript load method once the SWF has loaded */
flash.external.ExternalInterface.call("setTimeout", jsScope + "loaded()");
// Set event listeners for socket
// CONNECT
socket.addEventListener(flash.events.Event.CONNECT, function(e) : Void {
trace("Connected to server");
flash.external.ExternalInterface.call("setTimeout", jsScope + "connected()", 0);
}
);
// CLOSE
socket.addEventListener(flash.events.Event.CLOSE, function(e) : Void {
trace("Disconnected from server");
flash.external.ExternalInterface.call("setTimeout", jsScope + "disconnected()", 0);
}
);
// IO ERROR
socket.addEventListener(flash.events.IOErrorEvent.IO_ERROR, function(e) : Void {
trace("IOERROR : " + e.text);
flash.external.ExternalInterface.call("setTimeout", jsScope + "ioError('" + e.text + "')" ,0);
}
);
// SECURITY ERROR
socket.addEventListener(flash.events.SecurityErrorEvent.SECURITY_ERROR, function(e) : Void {
trace("SECURITY ERROR : " + e.text);
flash.external.ExternalInterface.call("setTimeout", jsScope + "securityError('" +e.text+ "')", 0);
}
);
// SOCKET DATA
socket.addEventListener(flash.events.ProgressEvent.SOCKET_DATA, function(e) : Void {
//var msg = socket.readMultiByte(socket.bytesAvailable,"gb2312");
var msg = socket.readUTFBytes(socket.bytesAvailable);
trace("Received : " + msg );
flash.external.ExternalInterface.call("setTimeout", jsScope + "receive('" + msg + "')", 0);
}
);
/* Set External Interface Callbacks */
// connect(host, port)
flash.external.ExternalInterface.addCallback("connect", connect);
// disconnect()
flash.external.ExternalInterface.addCallback("close", close);
// send()
flash.external.ExternalInterface.addCallback("send", send);
// log()
flash.external.ExternalInterface.addCallback("log", log);
} else {
trace("Flash external interface not available");
}
}
/**
* Connect to new socket server
* @param host The host the socket server resides on
* @param port The socket servers port
*/
static function connect(host : String, port : String) {
trace("Connecting to socket server at " + host + ":" + port);
socket.connect(host, Std.parseInt(port));
}
/**
* Disconnect the socket
*/
static function close() {
if (socket.connected) {
trace("Closing current connection");
socket.close();
} else {
trace("Cannot disconnect to server because there is no connection!");
}
}
/**
* Write string to the socket
*/
static function send(msg) {
if (socket.connected) {
trace("Writing '" + msg + "' to server");
//socket.writeMultiByte(msg,"gb2312");
socket.writeUTFBytes(msg);
socket.flush();
} else {
trace("Cannot write to server because there is no connection!");
}
}
/**
* Log
*/
static function log(msg) {
trace("log : "+msg);
}
}
编译
我使用了开源的haxe来编译,你也可以通过http://haxe.org/file/hxinst-win.exe获取它。编写完SocketBridge.hx以后,你需要在同一个目录下建一个compile.hxml文本文件,它的内容是:
-swf socket_bridge.swf
-swf-version 9
-main SocketBridge
在安装过haxe的情况下,只要你双击执行compile.hxml,便可以在同一目录下获得编译出的socket_bridge.swf 。
文章来自http://blog.sina.com.cn/s/blog_a787bfa90101brvs.html
相关文章推荐
- flash socket 从头开始构建一个web即时通讯系统 - 客户端
- 从头开始构建一个web即时通讯系统 - 基础 - web即时通讯系统的四种实现
- 从头开始构建一个嵌入式 Linux 发行版
- 在VS2015下配置websocket++,并用C++搭建一个简单的客户端
- 从头开始构建一个嵌入式 Linux 发行版
- 从头开始构建一个HTML电子邮件模板
- C H A P T E R 2 9 Building a Web Services Client 29章构建一个Web Services 客户端
- 从头开始构建一个嵌入式 Linux 发行版
- 一步一步用jenkins,ansible,supervisor打造一个web构建发布系统
- 从头开始构建一个嵌入式 Linux 发行版(转的)
- 利用Flash作为桥梁连接WEB页面和服务器端Socket通信,达到服务器主动"推"客户端的效果
- 从头开始构建一个嵌入式 Linux 发行版
- rhel5.8的系统上安装nginx+php(FastCGI)+mysql 来构建一个高效的web服务器
- 从头开始构建web前端应用——字符炸弹小游戏(一)
- 一步一步用jenkins,ansible,supervisor打造一个web构建发布系统
- 在 Web 项目中使用 Redis 快速构建系统缓存(单机版/集群版)
- socket实现多个客户端连接在一个服务器上
- 构建高可扩Web架构和分布式系统实战
- 给IBuySpy构建一个PlugIn系统
- 如何成为一个web前端,怎样系统的去学习![A篇]