尤为出色,Adobe提供了免费的开发版供大家学习,开发版支持10个客户端。本节内容就是教会大家如何使用 FMS 制作一个简单的聊天室。
学习目标
这一节要教会大家使用 FMS 通过SharedObject方式来实现聊天室的功能,先来看看完成后的作品。 (图一百零九)

图一百零九
学习目标
工作原理
本例中 FMS 聊天室的工作原理很简单,关键在于一个名为SharedObject的对象,我们可以把它看成所有聊天用户共享的全局对象,谁都可以读写它,如果A
用户发言就等于把一条对话追加到这全局变量中去,这个变量一旦发生改变便会通知所有其他在线聊天用户说:“同志们我的内容被更新啦”,其它客户便
可以去从这个变量 中取得最新的聊天记录,从而知道刚才A说了什么。稍微有点复杂,看一遍没看懂的同学,请认真地逐字逐句的把前面这段话好好理解,
这是聊天室现原理所在。
准备工作
1、下载工具
FMS :FMS 3.5(需要注册一个Adobe的账号) Servlet 容器:Tomcat 6.0
2、安装 FMS 3.5。
遇到下图这一步,是让你输入序列号,当然我们肯定没有,所以空着直接 Next。不输入序列号我们的 FMS就会成为开发版可以永久使用,但是最多只能支持10个客户端。(图一百一十)
之后会让你选择安装 Apache 服务器,由于我们在前几节课程中都是使用的 Tomcat,因此这一步就不安装了。 (图一百一十一)
再接下去就是要配置 FMS 的管理员账号了。 (图一百一十二)
最后是配置 FMS Server 的端口以及 Server 控制台的访问端口,系统默认是 1935,80,1111这3个端口,请确保没有被其它程序占用。(图一百一十三)
3、在 FMS 安装目录下的“applications”文件夹下建立一个名为“myApp”的文件夹,作为 Server 端项目根路径。以后我们的 SharedObject 对象便会
存放在这个位置。(图一百一十四)
4、在开始菜单中可以看见一些按钮,蓝色部分是打开服务器控制台,红色部分是关闭 FMS 服务,绿色部分是打开 FMS 服务。
点击蓝色部分按钮输入之前设置的账号可进入控制台。
实现步骤
1、建立 Flex 项目,因为我们做的是聊天室,这个工程架设在 Web 容器中(如 Tomcat 等)中会更加便于我们调试,所以我们在服务器技术里选择“J2EE”,由于这里服务端技术使用的是 fms,因此我们将“使用远程对象访问服务”给勾去后点击“下一步”。(图一百一十七)
2、之后我们对项目进行服务器配置。
- Web 根目录:设置为 Tomcat 的项目发布目录。
- 根 URL :设置为访问 Tomcat 的根地址,注意!为了便于局域网内的其他同学观摩你的作品,请务必使用ip地址,而非localhost。
- 输出路径:系统会自动指定,无需自己设置。
- 最后点击“验证配置”,待没有错误提示后便可以点击“完成”,结束工程的设置。(图一百一十八)
3、绘制简单的聊天界面,一个 TextArea 用于显示对话,一个 TextInput 用于输入用户昵称,一个 TextInput 用于输入消息,一个 Button 按钮发送对话。 (图一百一十九)
设置完后我们顺便为这些控件设置下标示。“textAreaContent”,“textInputName”,“textInputMessage”,“buttonSend”等。
4、我们定一个 Message Bean 来记录每一条对话。结构如下,分别是昵称,消息内容,时间。
package cn.airia.fb4.vo
{
public class Message
{
public function Message()
{
}
public var nickname:String;
public var msg:String;
public var time:Date;
}
}
5、接下去开始编码,首先我们定义一些变量。
private var netConnection:NetConnection;
private var serverApp:String = "rtmp://192.168.1.101/myApp";
private var talkSO:SharedObject;
netConnection:可以认为它是 Flex 与 FMS 通讯的桥梁。 serverApp:配置的是 FMS 服务的地址,注意这里使用的是rtmp协议。 talkSO:一个SharedObject对象,可以把它看成一个供所有聊天室用户存放聊天记录的全局对象。
6、在程序初始化执行一些操作。
private function init():void
{
netConnection = new NetConnection();
buttonSend.addEventListener(MouseEvent.CLICK,sendMessage);
netConnection.addEventListener(NetStatusEvent.NET_STATUS,netStatusHandler);
netConnection.addEventListener(AsyncErrorEvent.ASYNC_ERROR,asyncErrorHandler);
netConnection.connect(serverApp);
}
NetStatusEvent.NET_STATUS:用于监听连接状态。 AsyncErrorEvent.ASYNC_ERROR:是用于监听一些连接中的错误信息。 netConnection.connect(serverApp):这句的作用是正式开始连接 FMS 服务器。
这里主要是加一些监听。
NetStatusEvent.NET_STATUS的回调函数netStatusHandler用于根据服务器返回状态判断是否连接成功。
private function netStatusHandler(evt:NetStatusEvent):void
{
if(evt.info.code == "NetConnection.Connect.Success")
{
talkSO = SharedObject.getRemote("talk",netConnection.uri,false);
talkSO.addEventListener(SyncEvent.SYNC,talkSOHandler);
talkSO.addEventListener(AsyncErrorEvent.ASYNC_ERROR,asyncErrorHandler);
talkSO.connect(netConnection);
}
else
{
Alert.show("connect failed "+evt.info.code);
}
}
我们可以看到当服务器返回的 code 为“NetConnection.Connect.Success”时表示连接成功,那么我们就可以开始对这个全局共享变量talkSO
进行一些操作了。
SharedObject.getRemote("talk",netConnection.uri,false);这句的意思是,跑到 FMS 服务器下找“talk”这个文件,如果没有则新建一个用以存放
我们的全局变量,另外第三个参数的false的意思,就是说这个文件是临时的,当 FMS 服务器关闭时这个“talk”就被删除了。
小测试1:思考以下2个问题,如果回答不出,请重新阅读或放弃本教程。
netConnection.uri的内容及作用是什么? 第三个参数如果是 true 是代表什么?
talkSO.addEventListener(SyncEvent.SYNC,talkSOHandler);这句的作用比较关键,它监听的是talkSO变量也就是“talk”文件的内容有没有被其它用户
改写。
talkSO.connect(netConnection);这句例行公事,把前面对于 talkSO 的设置通过桥梁 netConnection 与 FMS 服务器扯上关系,大家死记硬背即可。
小测试2:思考以下2个问题,如果回答不出,请重新阅读或放弃本教程。
talkSO.addEventListener(AsyncErrorEvent.ASYNC_ERROR,asyncErrorHandler); 这句意思是什么?
7、桥梁,全局变量什么的都设置好了,接下去就是核心代码了。
private function sendMessage(evt:MouseEvent):void
{
var array:ArrayCollection = new ArrayCollection();
if(talkSO.data.msgList != null)
{
convertArrayCollection(array,talkSO.data.msgList as ArrayCollection);
}
var message:Message = new Message();
message.nickname = textInputName.text;
message.msg = textInputMessage.text;
message.time = new Date();
array.addItem(message);
talkSO.setProperty("msgList",array);
textInputMessage.text = "";
}
“talkSO”有个data属性,是用来存放数据的,我们需要它来存放我们所有的聊天记录,这里给聊天记录的集合起个名字叫做“msgList”,这段代码
的作用就是把“msgList”拿下来,然后把用户的发言追加进去,然后通过talkSO.setProperty("msgList",array);这句把它写回 FMS 服务器去。
private function talkSOHandler(evt:SyncEvent):void
{
textAreaContent.text = "";
if(talkSO.data.msgList != null)
{
var tmp:ArrayCollection = new ArrayCollection();
convertArrayCollection(tmp,talkSO.data.msgList as ArrayCollection);
var formatter:DateFormatter = new DateFormatter();
formatter.formatString = "HH:NN:SS";
for(var i:int = 0;i<tmp.length;i++)
{
var message:Object = tmp.getItemAt(i) as Object;
var timeString:String = formatter.format(message.time);
var fullMsg:String = message.nickname + " at " + timeString + " said:" + message.msg;
textAreaContent.text = textAreaContent.text+fullMsg+"\n";
}
}
}
这段代码是对于“SyncEvent.SYNC”事件所作出的响应,当有用户更新了聊天记录时候就会触发执行。主要功能就是把聊天记录“msgList”从服务器
拿下来,然后遍历下所有对话,把它们打印在 TextArea 中。
private function convertArrayCollection(arrNew:ArrayCollection,arrOld:ArrayCollection):void
{
arrNew.removeAll();
for(var i:int = 0;i<arrOld.length;i++)
{
arrNew.addItemAt(arrOld.getItemAt(i),i);
}
}
这段代码作用是用于 ArrayCollection 的复制。
8、运行代码,叫上你局域网的朋友一起测试吧,你也可以自己开2个浏览器进行测试。当有客户端连接上,你跑去 FMS 的控制台可以看到一些连接信息。
总结:
这节我们学习了在 FMS 中利用 SharedObject 方式实现了简单聊天室,目的在于让各位同学了解 FMS 的工作机制,包括今后你们在实现视频会议的时候, 其实其中原理也是一样的。本人在以往 Flex3 的开发中发现 SharedObject 的性能和可靠性实在不敢恭维( Flex4 中尚未验证),因此请大家在实际项目 中慎用 SharedObject 进行频繁的读写操作。
思考:
使用 FMS 实现简单的视频录制和播放。 使用 FMS 实现简单的多人视频。










