在前一篇“FluorineFx:远程共享对象(Remote SharedObjects)”里,已经大致知道了在FluorineFX中如何使用RSO,这一篇将利用RSO完成一个简单的文本聊天室。
原理:
RSO对象中,创建二个属性:msg和online,分别用来保存"用户每次发送的聊天内容"以及"在线用户列表"
运行截图:
服务端代码:
using System.Collections; using FluorineFx.Messaging.Api; using FluorineFx.Messaging.Api.SO; namespace _03_RSO_Chat { public class ChatSecurityHandler : ISharedObjectSecurity { #region ISharedObjectSecurity Members //是否允许连接 public bool IsConnectionAllowed(ISharedObject so) { return true; } //是否允许创建rso对象(下面的代码仅允许创建名为chat的rso对象) public bool IsCreationAllowed(IScope scope, string name, bool persistent) { if (name=="chat") { return false; } else { return true; } } //是否允许删除 public bool IsDeleteAllowed(ISharedObject so, string key) { return false; } //是否允许rso对象向服务端send指定回调方法(下面的代码仅允许发送名为drop的回调方法) public bool IsSendAllowed(ISharedObject so, string message, IList arguments) { return true; } //rso对象的属性是否可写 public bool IsWriteAllowed(ISharedObject so, string key, object value) { return true; } #endregion } }
ChatApplication.cs
using FluorineFx.Messaging.Adapter; using FluorineFx.Messaging.Api; using FluorineFx.Messaging.Api.SO; using System.Collections; using System; using System.Collections.Generic; using System.Linq; namespace _03_RSO_Chat { public class ChatApplication : ApplicationAdapter { public override bool AppStart(IScope application) { RegisterSharedObjectSecurity(new ChatSecurityHandler());//注册刚才定义的安全处理Handler return base.AppStart(application); } /// <summary> /// 每当有新客户端连接到服务器时,该方法会被触发 /// </summary> /// <param name="connection"></param> /// <param name="parameters"></param> /// <returns></returns> public override bool AppConnect(IConnection connection, object[] parameters) { string userName = string.Empty, passWord = string.Empty; if (parameters.Length >= 2) { userName = parameters[0].ToString();//第一个参数当作用户名 passWord = parameters[1].ToString();//第二个参数当作密码 } if (string.IsNullOrEmpty(userName)) { userName = "游客" + (new System.Random()).Next(0, 9999).ToString(); } //if (userName == "jimmy.yang" && passWord == "123456")//安全性校验 //{ if (base.AppConnect(connection, parameters)) { //获取共享对象(position) ISharedObject iso = GetSharedObject(connection.Scope, "chat"); if (iso == null) { //创建共享对象 CreateSharedObject(connection.Scope, "chat", true); iso = GetSharedObject(connection.Scope, "chat"); } //更新聊天记录 iso.SetAttribute("msg", "<font color='#0000ff'>系统:</font><font color='#ff0000'>" + userName + "</font> 进入聊天室!</font>"); //处理在线名单 string[] online = iso.GetAttribute("online") as string[]; List<string> lst = new List<string>(); if (online == null) { lst.Add(userName); } else { lst.AddRange(online); } if (!lst.Contains(userName)) { lst.Add(userName); } iso.SetAttribute("online", lst.ToArray()); //更新connection的userName属性(退出时会用到) connection.Client.SetAttribute("userName", userName); return true; } else { RejectClient("连接失败,请检查服务端是否运行正常!"); return false; } //} //else //{ // RejectClient("用户名或密码错误"); // return false; //} } /// <summary> /// 每当用户断开连接时,触发此事件 /// </summary> /// <param name="connection"></param> public override void AppDisconnect(IConnection connection) { try { string userName = connection.Client.GetAttribute("userName") as string; //获取共享对象(position) ISharedObject iso = GetSharedObject(connection.Scope, "chat"); //发送离线通知 iso.SetAttribute("msg", "<font color='#0000ff'>系统:</font><font color='#ff0000'>" + userName + "</font> 离开了聊天室!</font>"); //处理在线名单 string[] online = iso.GetAttribute("online") as string[]; List<string> lst = new List<string>(); if (online == null) { lst.Add(userName); } else { lst.AddRange(online); } if (lst.Contains(userName)) { lst.Remove(userName); } iso.SetAttribute("online", lst.ToArray()); } catch { } base.AppDisconnect(connection); } } }
Flash客户端代码:
package { import fl.controls.Button; import flash.display.SimpleButton; import flash.display.Sprite; import flash.events.MouseEvent; import flash.events.NetStatusEvent; import flash.events.SyncEvent; import flash.net.NetConnection; import flash.net.SharedObject; import flash.text.TextField; import flash.events.KeyboardEvent; import flash.ui.Keyboard; public class Chat extends Sprite { private var _btnConn:Button; private var _nc:NetConnection; private var _remoteUrl:String; private var _rso:SharedObject; private var _txtAppName:TextField; private var _txtContent:TextField; private var _txtIP:TextField; private var _txtOnline:TextField; private var _txtPassWord:TextField; private var _txtPort:TextField; private var _txtSend:TextField; private var _txtUserName:TextField; public function Chat() { this._txtIP = txtIP; this._txtPort = txtPort; this._txtAppName = txtAppName; this._btnConn = btnConn; this._txtContent = txtContent; this._txtOnline = txtOnline; this._txtUserName = txtUserName; this._txtPassWord = txtPassWord; this._txtSend = txtSend; this._nc=new NetConnection(); this._nc.addEventListener(NetStatusEvent.NET_STATUS, net_status); //trace(this._btnLogin); this._btnConn.addEventListener(MouseEvent.CLICK, btnConn_Click); this._txtIP.text = "127.0.0.1"; this._txtPort.text = "1935"; this._txtUserName.text = "游客" + Math.floor(Math.random()*10000); this._txtPassWord.text = "123456"; } private function btnConn_Click(e:MouseEvent):void { _remoteUrl = "rtmp://" + this._txtIP.text + ":" + this._txtPort.text + "/" + this._txtAppName.text; //trace(this._remoteUrl); _nc.connect(this._remoteUrl, this._txtUserName.text, this._txtPassWord.text); _nc.client = this; } private function net_status(e:NetStatusEvent):void { //trace(e.info.code); if (e.info.code == "NetConnection.Connect.Success") { _rso = SharedObject.getRemote("chat",this._nc.uri,true); this._rso.addEventListener(SyncEvent.SYNC,sync_handler); this._rso.connect(this._nc); this._rso.client = this; this._txtContent.htmlText = "<font color='#009933'>服务端连接成功!</font><br/>"; this._txtSend.addEventListener(KeyboardEvent.KEY_UP,txtsend_key_up); } else { this._txtContent.htmlText = "<font color='#ff0000'>服务端连接失败!</font><br/>"; } } private function sync_handler(e:SyncEvent):void { //trace(this._rso.data.msg); //更新聊天记录 if (this._rso.data.msg != undefined) { var msg:String = this._rso.data.msg + "<br/>"; var msgTxt:String = msg.replace(/<.+?>/gi,""); var chatTxt:String = this._txtContent.htmlText.replace(/<.+?>/gi,""); //防止重复显示 if (chatTxt.indexOf(msgTxt)==-1) { this._txtContent.htmlText += msg; } //trace(msg); //trace(this._txtContent.htmlText); this._txtContent.scrollV = this._txtContent.maxScrollV; } //更新在线列表 if (this._rso.data.online != undefined) { this._txtOnline.text = (this._rso.data.online as Array).join('\n'); } } private function txtsend_key_up(e:KeyboardEvent):void { //trace(e); if (this._txtSend.text.length > 0 && e.ctrlKey && e.keyCode == Keyboard.ENTER) { this._rso.setProperty("msg","<font color='#ff0000'>" + this._txtUserName.text + "</font> 说:" + this._txtSend.text); this._txtSend.text = ""; } } } }
示例源文件下载:http://cid-2959920b8267aaca.office.live.com/self.aspx/Flash/FluorineFx^_Demo^_03.rar
另:flex环境下fluorineFx的rso应用,建议大家同步参看beniao兄的文章Flex与.NET互操作(十二):FluorineFx.Net的及时通信应用(Remote Shared Objects)(三)