FluorineFx:基于RSO(远程共享对象)的文本聊天室

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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Java成神之路

Java企业微信开发_09_身份验证之移动端网页授权(有完整项目源码)

在开始使用网页授权之前,需要先设置一下授权回调域。这里瞬间想到之前做JSSDK的时候,也设置过一个域名。二者本质上都是设置可信域名。

8763
来自专栏linjinhe的专栏

LevelDB:使用介绍

Get 接口和 Put 接口比较像,除了 leveldb::ReadOptions 参数是用来控制读操作的,具体见链接指向的代码。

6555
来自专栏xiaoheike

Neo4j批量插入(Batch Insertion)

代码可以在github上看到:https://github.com/neo4j/neo4j/blob/2.3.3/community/embedded-exam...

1792
来自专栏GuZhenYin

使用localResizeIMG3+WebAPI实现手机端图片上传

前言 惯例~惯例~昨天发表的使用OWIN作为WebAPI的宿主..嗯..有很多人问..是不是缺少了什么 - - 好吧,如果你要把OWIN寄宿在其他的地方...代...

2168
来自专栏林德熙的博客

UWP WPF 解决 xaml 设计显示异常

例如我创建一个用户控件 TsjcyubtnTtqtjem 那么就可以在构造函数添加下面代码

1712
来自专栏恰同学骚年

自己动手写一个简单的MVC框架(第一版)

  路由(Route)、控制器(Controller)、行为(Action)、模型(Model)、视图(View)

1432
来自专栏技术之路

Caliburn.Micro学习笔记(四)----IHandle<T>实现多语言功能

说一下IHandle<T>实现多语言功能 因为Caliburn.Micro是基于MvvM的UI与codebehind分离, binding可以是双向的所以我们想...

2257
来自专栏木宛城主

SharePoint 2013 创建 Site Collection

在之前的文章中,通过SharePoint Central Administration 创建了Web Application。在这篇文章中将继续SharePo...

2106
来自专栏哲学驱动设计

精通 WPF UI Virtualization

    本篇博客主要说明如何使用 UI Virtualization(以下简称为 UIV) 来提升 OEA 框架中 TreeGrid 控件的性能,同时,给出了一...

2389
来自专栏xiaoheike

Eclipse下maven使用嵌入式(Embedded)Neo4j创建Hello World项目

代码可以在github上看到:https://github.com/neo4j/neo4j/blob/2.3.3/community/embedded-exam...

1072

扫码关注云+社区