用red5和flex实现的一个小的聊天程序

程序的基本功能

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>

效果图:



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值