首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 媒体动画 > flex >

red5+flex兑现超简易群聊天功能

2012-08-29 
red5+flex实现超简易群聊天功能要说这个聊天功能有多简单,大家看图就知道真相了:??实现功能①输入用户名,连

red5+flex实现超简易群聊天功能

要说这个聊天功能有多简单,大家看图就知道真相了:


red5+flex兑现超简易群聊天功能


red5+flex兑现超简易群聊天功能

?

?

实现功能①输入用户名,连接到服务器,如果用户名为空或者重名又或者在线人数超出限制则暂时拒绝连接②从服务器获取在线用户列表③从服务器获取用户上线、下线通知④从服务器获得其他用户发送的消息内容

⑤向服务器发送自己输入的消息

?

?

?

实现代码那么按照【实现功能】提到的一步步说明实现方式:
①连接服务器在flash页面,“用户名”文本框输入一个用户名,点击连接按钮触发连接事件,为了防止用户重复点击连接按钮,在一个页面只存在一个netConnect对象,flex代码如下:
private var rtmpUrl:String = "rtmp://localhost/chatroom";private var netConn:NetConnection = null;protected function connectRed5(event:MouseEvent):void{//如果对象不存在,则创建对象if(netConn == null){netConn = new NetConnection();}//如果未与red5连接,则执行远程连接if(!netConn.connected){netConn.connect(rtmpUrl,txt_userName.text);//指定连接client,方便red5调用当前客户端的方法netConn.client = this;netConn.addEventListener(NetStatusEvent.NET_STATUS,function connStatus(e:NetStatusEvent):void{switch(e.info.code){//连接成功case "NetConnection.Connect.Success":l_connStatus.text = "连接成功";//调用服务器方法,获取在线用户列表getOnlineListInfo();break;//服务器断开case "NetConnection.Connect.Closed":l_connStatus.text = "连接断开";break;//能连上,但被拒绝访问case "NetConnection.Connect.Failed":l_connStatus.text = "连接失败";break;default:break;}});}}
public class NotifyAppConnectThread implements Runnable{private IScope scope;private String userName;public NotifyAppConnectThread(IScope scope,String userName){this.scope = scope;this.userName = userName;}@Overridepublic void run() {//通知其它用户该用户上线notifyAppConnect(scope,userName);}/** * Function  : 通知其它客户,用户上线信息 * @author   : bless<505629625@qq.com> * @param scope */private void notifyAppConnect(IScope scope,String userName){//遍历所有链接到服务器的客户端Collection<Set<IConnection>> col = scope.getConnections();for (Set<IConnection> set : col) {for (IConnection iConnection : set) {//通知有所客户端上线用户信息if(iConnection instanceof IServiceCapableConnection){IServiceCapableConnection sc = (IServiceCapableConnection) iConnection;sc.invoke("otherConnection_msg", new Object[]{userName});}}}}}?
??上面代码是通过rtmp方式访问red5名为的chatroom的项目,所以在red5服务器必须有一个chatroom项目,具体如何创建就不赘述了,网上有很多资料。我们还是主要关注chatroom项目里的核心handler,那么我在red5-web.xml定义了:
<bean id="web.handler"     singleton="true" />
?这是聊天室核心类,每当flex客户端通过NetConnect连接chatroom项目时,都会被ChatApplication监听,下面看ChatApplication是如何监听客户端连接的:
/** * 聊天室 核心类 */public class ChatApplication extends ApplicationAdapter {//存储在线用户的Map对象private Map<String,IConnection> onlineList = new HashMap<String,IConnection>();final String USER_NAME = "userName";final int MAX_ONLINE = 50;/** * 客户端连接成功时执行 */@Overridepublic boolean appConnect(IConnection arg0, Object[] arg1) {System.out.println(">>>>>>>>>>>>>>>>appConnect");//用户首次连接server 时触发if(!super.appConnect(arg0, arg1)){return false;}//获取用户名String userName = null;if(arg1!=null){userName = arg1[0].toString().trim();}else{return false;}//检查在线人数if(onlineList.size() >= MAX_ONLINE){callClient(arg0,"超过最大在线人数,请稍后重试!");return false;}//检查用户名是否重复if(onlineList.containsKey(userName)||"".equals(userName)){callClient(arg0,"用户名为空或已存在!");return false;}//检查用户名长度if(userName.length()>18){callClient(arg0,"用户名长度不能超过18位!");return false;}//将用户信息加入到Map中onlineList.put(userName, arg0);//向客户端设置属性:userNamearg0.getClient().setAttribute(USER_NAME, userName);//通知其它用户该用户上线new Thread(new NotifyAppConnectThread(arg0.getScope(), userName)).start();//notifyAppConnect(arg0.getScope(), userName);return true;}    .    .    ..............}
?每一个客户端连接服务器时,都会首先运行appConnect方法,如果方法返回true表示连接成功,flex客户端随后就可以持续访问,如果返回false则表示连接失败。在appConnect方法体内首先检查用户连接有效性,如果有效则通知其它用户“某某上线了”,同时所有客户端在线用户列表刷新。

?

?

②从服务器获取在线用户列表

那么从服务器获取在线用户列表就非常简单了,在每次flex接到用户上线下线通知时都会调用服务器方法:

?

/** * 【供red5调用的方法】 * 客户端与red5连接后,获取其它客户连接信息的方法 * */public function otherConnection_msg(userName:String):void{messageContent.text = messageContent.text + userName +" 上线啦!\r\n\r\n";getOnlineListInfo();}/** * [供red5调用的方法] * 服务器向客户端发送通知:有其它用户下线 * */public function otherDisconnect_msg(userName:String):void{messageContent.text = messageContent.text + userName +" 下线啦!\r\n\r\n";getOnlineListInfo();}
/** * 刷新在线用户列表 * */private function getOnlineListInfo():void{netConn.call(this.getOnlineList,new Responder(function result(coll:String):void{var array:Array = coll.split("\r\n");online_userlist.removeAll();for each(var str:String in array){var obj:Object = new Object();obj.label = str;online_userlist.addItem(obj);}}));}
?

flex是通过远程调用服务器方法,所以在服务器端必须有一个对于获取在线用户集合的方法:

?

/** * Function  : 获取用户列表 * @author   : bless<505629625@qq.com> * @return */public String getOnlineList(){StringBuffer sb = new StringBuffer();//把用户列表数据取出来Set<String> setUserName = onlineList.keySet();for (String string : setUserName) {sb.append(string+"\r\n");}return sb.toString();}

?

?

③从服务器获取用户上线、下线通知

某个客户端离线时,服务器的appDisconnect会运行,在方法内处理该客户端资料清理同时通知给其它用户:

下面是java代码:

?

/** * 客户端断开连接时自动执行 */@Overridepublic void appDisconnect(IConnection arg0) {System.out.println(">>>>>>>>>>>>>>>>>>appDisconnect");//清理离线用户的资料onlineList.remove(arg0.getClient().getAttribute(USER_NAME));//通知其它用户该用户离线new Thread(new NotifyAppDisconnectThread(arg0.getScope(), arg0.getClient().getAttribute(USER_NAME).toString())).start();//notifyAppDisconnect(arg0.getScope(),arg0.getClient().getAttribute(USER_NAME).toString());super.appDisconnect(arg0);}

?

通知其它用户,我使用了多线程的形式,这样不至于影响主线程的效率:

?public class NotifyAppDisconnectThread implements Runnable{private IScope scope;private String userName;public NotifyAppDisconnectThread(IScope scope,String userName){this.scope = scope;this.userName = userName;}@Overridepublic void run() {notifyAppDisconnect(scope,userName);}/** * Function  : 通知其它客户端,用户离线信息 * @author   : bless<505629625@qq.com> * @param scope * @param userName */private void notifyAppDisconnect(IScope scope,String userName){//遍历所有链接到服务器的客户端Collection<Set<IConnection>> col = scope.getConnections();for (Set<IConnection> set : col) {for (IConnection iConnection : set) {//通知有所客户端上线用户信息if(iConnection instanceof IServiceCapableConnection){IServiceCapableConnection sc = (IServiceCapableConnection) iConnection;sc.invoke("otherDisconnect_msg", new Object[]{userName});}}}}}
?

?

④从服务器获得其他用户发送的消息内容

⑤向服务器发送消息内容

这两步操作紧密关系到一起,只有客户端调用服务器发送消息方法,服务器才会给所有客户端发送最新消息内容,在flex端通过sendMsg方法(此方法是flex调用red5)发送消息,getMsg方法(此方法是red5调用felx)获取消息:

?

/** * 发送消息 * */protected function sendMsg():void{netConn.call(this.sendMessage,new Responder(function result():void{}),txt_msg.text);//清空输入框txt_msg.text = "";}/** * 【供red5调用的方法】 * 获取消息 * */public function getMsg(msg:String):void{messageContent.text = messageContent.text + msg;}
?

?

最后看服务器时如何发送消息的:

?

/** * Function  : 发送消息 * @author   : bless<505629625@qq.com> * @param userName * @param message */public void sendMessage(String message){//获取当前请求的客户端信息String userName_ = Red5.getConnectionLocal().getClient().getAttribute(USER_NAME).toString();//封装信息内容String msg = "<" +userName_ + ">  " + sdf.format(new Date()) + "\r\n" + message +"\r\n\r\n";Set<String> setUserName = onlineList.keySet();for (String string : setUserName) {IConnection iConnection = onlineList.get(string);//通知有所客户端信息if(iConnection instanceof IServiceCapableConnection){IServiceCapableConnection sc = (IServiceCapableConnection) iConnection;sc.invoke("getMsg", new Object[]{msg});}}}
?

?

至此一个简单的聊天程序就完成了,你可以尝试把flex编译生产的html、swf文件放到服务器部署,这样就可以在线访问了。

?

下面附代码源码。

red5版本:0.9.1

flex版本:4.0

1 楼 hnzhangshi 2012-03-14   写的很好,简单易懂,可做为入门的好例子!学习了

热点排行