在前一篇“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)(三)