程序的基本功能
1.用户连接、断开连接
2.显示用户登录列表
3.信息群聊
4.私聊
red5程序:ChatRoom.java
package com.red5; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.logging.Logger; import org.red5.server.adapter.ApplicationAdapter; import org.red5.server.api.IConnection; import org.red5.server.api.IScope; import org.red5.server.api.Red5; import org.red5.server.api.service.IServiceCapableConnection; import org.red5.server.api.so.ISharedObject; /** * @category 一个简单的聊天程序 * @author Administrator * */ public class ChatRoom extends ApplicationAdapter { private static Logger log = Logger.getLogger(ChatRoom.class.getName()); private Map<String, IConnection> clientDic = new HashMap<String, IConnection>(); /** * @category 客户端连接时调用 */ @Override public synchronized boolean connect(IConnection conn, IScope scope, Object[] params) { if(params.length == 0) { rejectClient("Must pass the login name."); } String loginname = params[0].toString(); conn.setAttribute("UserName", loginname); //如果用户不存在于当前的连接中,则将其加入 //如果不存在共享对象,则创建 if(clientDic.keySet().contains(loginname)) { rejectClient("The same user has logged in already"); } else { clientDic.put(loginname, conn); ISharedObject so = getSharedObject(scope, "UserSO"); if(so == null) { createSharedObject(scope, "UserSO", true); so = getSharedObject(scope, "UserSO"); } so.setAttribute("userlist", clientDic.keySet().toArray()); } return super.connect(conn, scope, params); } /** * @category 客户端失去连接时调用 */ @Override public synchronized void disconnect(IConnection conn, IScope scope) { String loginname = conn.getAttribute("UserName").toString(); if(loginname != null) { if(clientDic.keySet().contains(loginname)) { clientDic.remove(loginname); ISharedObject so = getSharedObject(scope, "UserSO"); if(so != null) { so.setAttribute("userlist", clientDic.keySet().toArray()); } } } super.disconnect(conn, scope); } /** * @category 发送全局消息,所有上线的人都能够看到 * @param params */ public void sendMessage(List<String> params) { IConnection conn = Red5.getConnectionLocal(); IScope scope = conn.getScope(); ISharedObject so = getSharedObject(scope, "UserSO"); log.info("Server: call sendMessage and params " + params.get(0)); so.sendMessage("receiveMsg", params); } /** * @category 发送私聊信息,只有被选中的人能够看到信息 * @param params */ public void sendPrvMessage(List<String> params) { if(params.size() == 3) { String sender = params.get(0); String content = params.get(1); String receiver = params.get(2); if(clientDic.keySet().contains(receiver)) { IConnection conn = clientDic.get(receiver); if(conn instanceof IServiceCapableConnection) { IServiceCapableConnection sc = (IServiceCapableConnection) conn; log.info("Server: call sendPrvMessage and sender->" + sender + " content->" + content + " receiver->" + receiver); sc.invoke("receivePrvMsg", new Object[]{sender,content}); } } } } public Boolean appStart() { return true; } public void appStop() { } }
1.red5-web.properties
webapp.contextPath=/chatRoom webapp.virtualHosts=localhost, 127.0.0.1
2.red5-web.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="placeholderConfig" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="location" value="/WEB-INF/red5-web.properties" /> </bean> <bean id="web.context" class="org.red5.server.Context" autowire="byType" /> <bean id="web.scope" class="org.red5.server.WebScope" init-method="register"> <property name="server" ref="red5.server" /> <property name="parent" ref="global.scope" /> <property name="context" ref="web.context" /> <property name="handler" ref="web.handler" /> <property name="contextPath" value="${webapp.contextPath}" /> <property name="virtualHosts" value="${webapp.virtualHosts}" /> </bean> <bean id="web.handler" class="com.red5.ChatRoom" singleton="true" /> <!-- this will support calling methods through "myhandler.<methodName>" --> <!-- <bean id="myhandler.service" class="the.path.to.my.ServiceHandler" singleton="true" /> --> </beans>
3.web.xml
<?xml version="1.0" encoding="ISO-8859-1"?> <web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4"> <display-name>firstapp</display-name> <context-param> <param-name>globalScope</param-name> <param-value>default</param-value> </context-param> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/red5-*.xml</param-value> </context-param> <context-param> <param-name>locatorFactorySelector</param-name> <param-value>red5.xml</param-value> </context-param> <context-param> <param-name>parentContextKey</param-name> <param-value>default.context</param-value> </context-param> <context-param> <param-name>log4jConfigLocation</param-name> <param-value>/WEB-INF/log4j.properties</param-value> </context-param> <context-param> <param-name>webAppRootKey</param-name> <param-value>/chatRoom</param-value> </context-param> <security-constraint> <web-resource-collection> <web-resource-name>Forbidden</web-resource-name> <url-pattern>/streams/*</url-pattern> </web-resource-collection> <auth-constraint/> </security-constraint> </web-app>
flex程序:chatRoom.mxml
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"> <mx:Script> <![CDATA[ import mx.charts.chartClasses.StackedSeries; import mx.formatters.SwitchSymbolFormatter; import mx.controls.Alert; private var conn:NetConnection; private var so:SharedObject; private var rtmpURL:String = "rtmp://localhost/chatRoom"; private function connHandler(evnet:Event):void { var loginname:String = loginName.text; if(loginname == "") { Alert.show("login name is null"); return; } else { if(conn == null) { initNetConnection(loginname); } } } /** * 初始化连接 */ private function initNetConnection(loginname:String):void { conn = new NetConnection(); conn.addEventListener(NetStatusEvent.NET_STATUS, netStatus); conn.connect(rtmpURL, loginname); } private function netStatus(event:NetStatusEvent):void { if("NetConnection.Connect.Success" == event.info.code) { sendBtn.enabled = true; so = SharedObject.getRemote("UserSO", conn.uri, true); so.addEventListener(SyncEvent.SYNC, onSync); so.client = this; //设置群聊时接收到消息的窗体 conn.client = this; //设置私聊时接收到消息的窗体 so.connect(conn); } } private function onSync(event:SyncEvent):void { for(var i:Object in event.changeList) { var changeObj:Object = event.changeList[i]; switch(changeObj.code) { case "success": break; case "change": userList.dataProvider = so.data.userlist; break; } } } /** * 失去连接 */ private function disconnhandler(event:Event):void { if(conn != null && conn.connected) { conn.close(); var nularr:Array = new Array(); userList.dataProvider = nularr; } } /** * 发送消息 */ private function sendHandler(event:Event):void { if(conn != null && conn.connected) { if(IsPrivate.selected) { if(userList.selectedIndex == -1) { Alert.show("must choose a user first"); } else { var pusername:String = userList.selectedItem.toString(); if(pusername == loginName.text) { Alert.show("can't say privately to self"); } else { //调用服务器端的私聊函数 conn.call("sendPrvMessage", null, loginName.text, loginName.text + " says privately: " + chatWord.text, pusername); chatWord.text = ""; } } } else { if(chatWord.text != "") { //调用服务器端的群聊函数 conn.call("sendMessage", null, loginName.text + " says: " + chatWord.text); chatWord.text = ""; } } } } /** * 接收私聊信息并显示 */ public function receivePrvMsg(sender:String, msg:String):void { chatArea.text += msg + "\n"; } /** * 接收群聊信息并显示 */ public function receiveMsg(msg:String):void { chatArea.text += msg + "\n"; } ]]> </mx:Script> <mx:Panel width="585" height="480" layout="absolute" title="ChatRoom" horizontalCenter="0" verticalCenter="0"> <mx:Label x="46" y="26" text="Login Name:"/> <mx:TextInput x="125" y="24" id="loginName"/> <mx:Button x="314" y="24" label="Connect" id="connBtn" click="connHandler(event)"/> <mx:Button x="406" y="24" label="DisConnect" id="disconnBtn" click="disconnhandler(event)"/> <mx:TextArea x="241" y="73" width="255" height="248" id="chatArea"/> <mx:Label text="Chat:" horizontalCenter="-140" verticalCenter="175"/> <mx:TextInput x="169" y="384" width="249" id="chatWord"/> <mx:Button x="426" y="384" label="send" id="sendBtn" width="68" enabled="false" click="sendHandler(event)"/> <mx:CheckBox x="68" y="340" label="Private Chat" id="IsPrivate"/> <mx:TileList x="46" y="73" width="164" height="248" id="userList" columnCount="1" direction="vertical"></mx:TileList> </mx:Panel> </mx:Application>
效果图: