FluorineFx + Flex视频聊天室案例开发----服务器端

FluorineFx + Flex视频聊天室案例开发----服务器端

      在我之前的一篇文章里曾经介绍过FluorineFx的ApplicationAdapter的基本步骤,以及使用FluorineFx的ApplicationAdapter来开发及时通信应用的相关知识点。ApplicationAdapter应用最终需要部署到支持FluorineFx服务的Web应用(ASP.NET网站)上,如下图则表示了FluorineFx应用的目录结构。

                  

       对于使用过FluorineFx开发应用的朋友来说,这个图在熟悉不过了。要使用FluorineFx开发及时通信应用,项目结构就必须这样搭建,首先看看本篇案例的解决方案截图:

                  

      从上面的解决方案截图可以看到,整个项目由两部分构成,一个是FluorineFx的类库,封装了远程服务(RemotingService)接口和及时通信应用程序(ApplicationAdapter)。另一个则是FluorineFx网站(和ASP.NET网站没多大的区别,不同的是其中加入了FluorineFx的一些相关配置)。

      为了方便演示案例本篇就直接使用的 Access做为数据库,根据数据库的字段结构建立了一个数据传输对象(DTO),同时为该DTO对象标记[FluorineFx.TransferObject],以使其可以作为FluorineFx的数据传输对象使用。

namespace  ChatRoom.Services.DTO
{
    
///   <summary>
    
 用户信息(数据传输对象)
    
</summary>
    [FluorineFx.TransferObject]
    
public   class  UserInfo
    {
        

        
 构造方法
        
          UserInfo() { }

        
int  ID {  get set ; }

        
string  UserName {   NickName {   Password {   HeadImage {  ; }
    }
}

 

      远程服务接口(DataService)提供了用户注册,登陆等最基本的通信接口方法,在了解通信接口之前首先学习一个工具类,该类的提供了一个将DataTable类型数据转话为IList<Object>类型返回,详细代码如下:

 ChatRoom.Services.Utils
{
     static  ConvertUtils
    {
        
 提供将DataTable类型对象转换为List集合
        
</summary> <param name="table"></param> <returns></returns>  List < T >  ConvertToList (DataTable table)  where  T :  new ()
        {
            
// 置为垃圾对象
            List  list  = null ;

            
if  (table  != )
            {
                DataColumnCollection columns 
 table.Columns;
                
 columnCount   columns.Count;
                T type 
 T();
                Type columnType 
 type.GetType();
                PropertyInfo[] properties 
 columnType.GetProperties();

                
 (properties.Length  ==  columnCount)
                {
                    list 
();
                    
foreach  (DaTarow currentRow  in  table.Rows)
                    {
                        
for  (  i  0 ; i   columnCount; i ++ )
                        {
                            
 j  ; j   properties.Length; j )
                            {
                                
 (columns[i].ColumnName   properties[j].Name)
                                {
                                    properties[j].SetValue(type, currentRow[i], 
);
                                }
                            }
                        }
                        list.Add(type);
                        type 
 T();
                    }
                }
                
else
                {
                    list 
;
                }
            }
            

            {
                
throw  ArgumentNullException( " 参数不能为空 " );
            }
            
return  list;
        }
    }
}

      

      下面是使用FluorineFx提供的远程服务接口的详细定义:

 ChatRoom.Services
{
    [RemotingService]
      DataService
    {
        
 DataService()
        {
        }

        
 用户注册
        
<param name="info"></param> bool  Register(UserInfo info)
        {
            info.Password 
 FormsAuthentication.HashPasswordForStoringInConfigFile(info.Password,  MD5 );
            StringBuilder CommandText 
 StringBuilder( insert into UserInfo values ( );
            CommandText.Append(
.Format( '{0}','{1}','{2}','{3}') , info.UserName, info.Password, info.NickName, info.HeadImage));

            
try  row   DataBase.Executesql(CommandText.ToString());
                
 (row  )
                    
true ;
                
false ;
            }
            
catch  (Exception ex)
            {
                
;
            }
        }

        
 用户登录
        
 UserInfo Login(UserInfo info)
        {
            info.Password 
select * from UserInfo where  UserName='{0}' and Password='{1}'
            {
                DataTable table 
 DataBase.ExecuteQuery(CommandText.ToString());
                
)
                {
                    
 ConvertUtils.ConvertToList UserInfo (table)[ ];
                }
                
;
            }
        }
    }
}

 

      FluorineFx.Messaging.Adapter.ApplicationAdapter做为新的应用程序的基类,提供了客户端与应用程序之间通信的接口方法、数据流服务以及共享对象服务等。它能够时时处理应用程序的启动、停止、客户端的连接和断开等及时操作。

      在本篇案例项目中,我所建立的ApplicationAdapter为ChatRoomApplication,用来提供启动及时应用服务器,接受客户端连接和断开以及视频流服务等功能。这里需要注意一点,在接受客户端连接的时候业务处理流程,在应用程序启动的时候就将会创建一个共享对象,用来保存在线用户列表。

override  AppStart(IScope application)
{
    
用户共享对象     CreateSharedobject(application,0)">OnLineUsers );

    
base .AppStart(application);
}

 

      当用户通过客户端连接服务器的时候,将用户信息传递到服务器,服务器端接受到数据后将会对用户数据进行验证(验证用户名和密码是否匹配),如果验证失败则直接返回false表示连接服务器失败,如果验证通过则设置当前连接的属性并连接到共享对象,然后取出共享对象里的在线用户列表数据,判断当前连接到服务器的用户是否在线,如果用户已在线则返回false表示用户登录失败,并给于提示当前用户已经登录。如果用户没有存在于共享里则表示当前连接的用户没有登录,那么就将当前连接的用户信息写入共享对象,客户端会通过异步事件处理函数接收到最新的在线用户列表数据。

 

 

 AppConnect(IConnection connection,255)">object [] parameters)
{
    UserInfo info 
 ((Dictionary )parameters[ ])[ 0 as  UserInfo;

    connection.Client.SetAttribute(
UserName 连接到共享对     ISharedobject users   GetSharedobject(connection.Scope,0)">);
    
 (users  )
    {
        
this .CreateSharedobject(connection.Scope,0)">);
        users 
);
    }
    

    {
        List
 onLineUserList   users.GetAttribute( UserInfo ;
        
 (onLineUserList  )
        {
            List
 tempList   (from u   onLineUserList
                                       
 u.UserName   info.UserName
                                       select u
                                       ).ToList();
            
 (tempList.Count  )
            {
                
Server RPC                  .CallClientMethod(connection,0)">onLogined 当前用户已经登录 );
                

            {
                onLineUserList.Add(info);
                users.SetAttribute(

        {
            onLineUserList 
 { info };
            users.SetAttribute(
.AppConnect(connection, parameters);
}

 

      OK,到这里就完成了对用户进行有效验证和接受与拒绝连接的功能,那么如果是用户下线了或是无意之间关闭了浏览器呢?这种情况应当如何去处理,如果不处理的话那么用户是不是会一直卡在线上呢?答案是肯定的。FluorineFx为此也提供了接口来处理用户下线的操作,那么在这里我们需要做什么呢?需要做的就是取出当前退出系统的客户端连接属性值,然后在取出共享对象里的在线用户列表数据,根据用户连接时所设置的属性进行循环判断,找到当前退出系统的用户数据,最后将他从共享对象里删除,服务器端的共享对象一但改变,所有连接到服务器的客户端都会通过共享对象的异步事件得到最新的数据,用来更新客户端的显示列表。

void  Appdisconnect(IConnection connection)
{
    
 userName   connection.Client.GetAttribute( ;

    ISharedobject users 
)
    {
        List
 onLineUserList.FindAll(c  =>  c.UserName.Length  );
            
 (var item   tempList)
            {
                
 (item.UserName.Equals(userName))
                {
                    onLineUserList.Remove(item);
                }
            }
            users.SetAttribute(
.Appdisconnect(connection);
}

 

      到这里服务器端的开发就基本完成了,现在就需要将这个ApplicationAdapter配置好,然后启动通过网站启动服务,Flex或者是Flash就可以通过rtmp协议连接了。首先需要配置的是rtmp协议通信信道:

< channel-deFinitio id ="my-rtmp"  class ="mx.messaging.channels.RTMPChannel" >
    
endpoint  uri ="rtmp://{server.name}:2777" ="flex.messaging.endpoints.RTMPEndpoint" /> properties
        
idle-timeout-minutes 20 </ channel-deFinition >

 

      然后就是在应用目录下面配置ApplicationAdapter,指定当前这个应用又那一个Adapter来处理。建立app.config文件进行如下配置:

<? xml version="1.0" encoding="utf-8" ?> configuration
  
application-handler  type ="ChatRoom.Services.ChatRoomApplication" >

 

      在下一篇中我将详细介绍客户端的开发,包括使用RTMP协议连接到服务器,使用远程共享对象做在线用户列表和聊天消息发送,以及通过NetStream建立视频流连接实现视频聊天等相关功能

 

版权说明

  本文属原创文章,欢迎转载,其版权归作者和博客园共有。  

  作      者:Beniao

 文章出处:http://beniao.cnblogs.com/  或  http://www.voidcn.com/article/p-ugwheald-bnx.html

相关文章

一:display:flex布局display:flex是一种布局方式。它即可以...
1. flex设置元素垂直居中对齐在之前的一篇文章中记载过如何...
移动端开发知识点pc端软件和移动端apppc端软件是什么,有哪些...
最近挺忙的,准备考试,还有其他的事,没时间研究东西,快周...
display:flex;把容器设置为弹性盒模型(设置为弹性盒模型之后...
我在网页上运行了一个Flex应用程序,我想使用Command←组合键...