flex + red5实现视频会议

38 篇文章 0 订阅

      公司最近要在系统中加视频会议的功能,让我探索,我选择了最流行的red5来实现,网上有一对一聊天的demo,找不到多对多聊天的,也没有具体介绍系统搭建的过程,我通过自己的摸索,将实现的过程和大家一起分享。java的web项目添加flex支持在此不再详述,项目文件结构如图:




 
 


 web.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<web-app
   version="2.4"
   xmlns="http://java.sun.com/xml/ns/j2ee"
   xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<!--
    ** For use with servlet v2.5 replace the lines above with these
    version="2.5"
    xmlns="http://java.sun.com/xml/ns/javaee"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-->
	<display-name>Red5ChartRoom</display-name>

	<context-param>
		<param-name>globalScope</param-name>
		<param-value>default</param-value>
	</context-param>

	<context-param>
		<param-name>parentContextKey</param-name>
		<param-value>default.context</param-value>
	</context-param>

	<context-param>
		<param-name>webAppRootKey</param-name>
		<param-value>@webapp.root.key@</param-value>
	</context-param>

	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>WEB-INF/classes/*-web.xml</param-value>
	</context-param>

	<listener>
		<listener-class>org.red5.server.war.WarLoaderServlet</listener-class>
	</listener>

    <listener>
        <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
    </listener>

	<servlet>
		<servlet-name>gateway</servlet-name>
		<servlet-class>org.red5.server.net.servlet.AMFGatewayServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>

	<servlet>
		<servlet-name>rtmpt</servlet-name>
		<servlet-class>org.red5.server.net.rtmpt.RTMPTServlet</servlet-class>
		<load-on-startup>2</load-on-startup>
	</servlet>
	
	 <!-- MessageBroker Servlet -->
 <servlet>
  <display-name>MessageBrokerServlet</display-name>
  <servlet-name>MessageBrokerServlet</servlet-name>
  <servlet-class>flex.messaging.MessageBrokerServlet</servlet-class>
  <init-param>
   <param-name>services.configuration.file</param-name>
   <param-value>/WEB-INF/flex/services-config.xml</param-value>
  </init-param>
  <load-on-startup>11</load-on-startup>
 </servlet>

	<servlet-mapping>
		<servlet-name>gateway</servlet-name>
		<url-pattern>/gateway</url-pattern>
	</servlet-mapping>

    <servlet-mapping>
        <servlet-name>rtmpt</servlet-name>
        <url-pattern>/fcs/*</url-pattern>
    </servlet-mapping>

	<servlet-mapping>
		<servlet-name>rtmpt</servlet-name>
		<url-pattern>/open/*</url-pattern>
	</servlet-mapping>

	<servlet-mapping>
		<servlet-name>rtmpt</servlet-name>
		<url-pattern>/idle/*</url-pattern>
	</servlet-mapping>

	<servlet-mapping>
		<servlet-name>rtmpt</servlet-name>
		<url-pattern>/send/*</url-pattern>
	</servlet-mapping>

	<servlet-mapping>
		<servlet-name>rtmpt</servlet-name>
		<url-pattern>/close/*</url-pattern>
	</servlet-mapping>

	 <servlet-mapping>
 		 <servlet-name>MessageBrokerServlet</servlet-name>
 	 	<url-pattern>/messagebroker/*</url-pattern>
 	</servlet-mapping>
 
	<welcome-file-list>
		<welcome-file>login.html</welcome-file>
		<welcome-file>index.html</welcome-file>
		<welcome-file>index.htm</welcome-file>
	</welcome-file-list>

	<security-constraint>
		<web-resource-collection>
			<web-resource-name>Forbidden</web-resource-name>
			<url-pattern>/WEB-INF/*</url-pattern>
		</web-resource-collection>
		<auth-constraint />
	</security-constraint>

	<security-constraint>
		<web-resource-collection>
			<web-resource-name>Forbidden</web-resource-name>
			<url-pattern>/persistence/*</url-pattern>
		</web-resource-collection>
		<auth-constraint />
	</security-constraint>

	<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>


 red5ChartRoom-web.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:lang="http://www.springframework.org/schema/lang"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                           http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-3.0.xsd">
<bean id="web.context.chatroom" class="org.red5.server.Context">
	<property name="scopeResolver" ref="red5.scopeResolver"></property>
	<property name="clientRegistry" ref="global.clientRegistry"/>
	<property name="serviceInvoker" ref="global.serviceInvoker"/>
	<property name="mappingStrategy" ref="global.mappingStrategy"/>
</bean>
<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.chatroom"/>
	<property name="handler" ref="web.handler.chatroom"/>
	<property name="contextPath" value="/Red5ChatRoom"/>
	<property name="virtualHosts" value="*,localhost,localhost:8080,127.0.0.1:8080"/>
</bean>
<bean id="web.handler.chatroom" class="com.chinahrt.chat.VedioChatApplication"/>
</beans>

 

red5.properties

# Socket policy
policy.host=0.0.0.0
policy.port=843

# HTTP
http.host=0.0.0.0
http.port=5080
https.port=8443

# RTMP
rtmp.host=0.0.0.0
rtmp.port=1935
rtmp.io_threads=16
rtmp.connect_threads=4
rtmp.send_buffer_size=271360
rtmp.receive_buffer_size=65536
rtmp.ping_interval=1000
rtmp.max_inactivity=60000
rtmp.tcp_nodelay=true

# RTMPS
rtmps.host=0.0.0.0
rtmps.port=8443
rtmps.ping_interval=5000
rtmps.max_inactivity=60000
rtmps.max_keep_alive_requests=-1
rtmps.max_threads=20
rtmps.acceptor_thread_count=2
rtmps.processor_cache=20
# RTMPS Keystore Password
rtmps.keystorepass=password

# RTMPT
rtmpt.host=0.0.0.0
rtmpt.port=8088
rtmpt.ping_interval=5000
rtmpt.max_inactivity=60000
rtmpt.max_keep_alive_requests=-1
rtmpt.max_threads=20
rtmpt.acceptor_thread_count=2
rtmpt.processor_cache=20

# MRTMP
mrtmp.host=0.0.0.0
mrtmp.server=localhost
mrtmp.port=9035
mrtmp.event_threads_core=4
mrtmp.event_threads_max=32
# event threads queue: -1 unbounded, 0 direct (no queue), n bounded queue
mrtmp.event_threads_queue=0
mrtmp.event_threads_keepalive=60
mrtmp.send_buffer_size=271360
mrtmp.receive_buffer_size=65536
mrtmp.ping_interval=5000
mrtmp.max_inactivity=60000
mrtmp.tcp_nodelay=true

# Debug proxy (needs to be activated in red5-core.xml)
proxy.source_host=127.0.0.1
proxy.source_port=1936
proxy.destination_host=127.0.0.1
proxy.destination_port=1935

# JMX
jmx.rmi.port.registry=9999
jmx.rmi.port.remoteobjects=
jmx.rmi.host=127.0.0.1
jmx.rmi.ssl=false


red5.config_root=red5.config_root
red5.root=E\:apache-tomcat-6.0.33

 

java代码

package com.chinahrt.chat;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.python.antlr.PythonParser.return_stmt_return;
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;
import org.red5.server.api.stream.IBroadcastStream;

/**
 * createBy ZYN
 *
 * createTime 2011-9-16 下午03:33:15
 *
 * desc 视频聊天服务器
 *
 */
public class VedioChatApplication extends ApplicationAdapter {
	
	private IScope appScope;
	
	private String userName;
	//共享存贮在线用户
	private ISharedObject listSO;
	
	private Map<String,IConnection> onlineList = new HashMap<String,IConnection> ();//在线用户表
	
	//程序运行
	//程序运行时志向 
	public boolean appStart(IScope app) { 
	  if (!super.appStart(app)) { 
	      return false; 
	  } 
	  appScope = app; 
	  return true; 
	} 
	@Override 
	public boolean appConnect(IConnection arg0, Object[] arg1) { 
	  /** 
	   *  用户首次连接server 时触发,检查用户是否重复登录,将用户添加到在线用户表中 
	   */ 
	  String userId=arg0.getClient().getId(); 
	  if(!super.appConnect(arg0, arg1)){ 
	   return false; 
	  } 
	  if (arg1 != null ) { 
	   userName = (String) arg1[0]; 
	  } 
	  if(onlineList.get(userName) != null){ 
	   rejectClient("请不要重复登录"); 
	   return false; 
	  } 
	  onlineList.put(userName, arg0); 
	  listSO = getSharedObject(appScope, "listSO", false); 
	  listSO.setAttribute(userId, userName); 
	  System.out.println("The user:"+userName+","+userName+" logined successfully"); 
	  return true; 
	} 
	/** 
	  * 通知所有人当前用户登录 
	  * @param params 
	  */ 
	public void getOnloadUser(Object[] params) {   
	  String clientName = params[0].toString();  
	  if(null == clientName || "".equals(clientName)) { 
	     return ; 
	   } 
	  //给所有客户端数据 
	   IScope scope = Red5.getConnectionLocal().getScope(); 
	   Iterator it = scope.getConnections().iterator(); 
	   for (;it.hasNext();) { 
	    Set connections = (Set)it.next(); 
	    IConnection tempConn = (IConnection)connections.iterator().next(); 
	    if (tempConn instanceof IServiceCapableConnection) { 
	     IServiceCapableConnection sc = (IServiceCapableConnection) tempConn; 
	     sc.invoke("result_getOnloadUser", new Object[]{clientName}); 
	    } 
	   } 
	} 
	//聊天 
	  public void sayToAll(Object[] params) { 
	   IConnection conn = Red5.getConnectionLocal(); 
	   String user_id = conn.getClient().getId(); 
	   String clientName =(String) listSO.getAttribute(user_id); 
	   System.out.println("************发言者是:"+clientName); 
	   String sayToName=params[0]==null?"":params[0].toString().trim();   
	   String sayWhat=params[1]==null?"":params[1].toString().trim(); 
	   if("".equals(sayToName)||"All".equals(sayToName))// 发消息给聊天室的所有人. 
	   { 
	    IScope scope = Red5.getConnectionLocal().getScope(); 
	    Iterator it = scope.getConnections().iterator();  
	    for (;it.hasNext();) { 
	      Set connections = (Set)it.next(); 
	      IConnection tempConn = (IConnection)connections.iterator().next(); 
	     if (tempConn instanceof IServiceCapableConnection) { 
	         IServiceCapableConnection sc = (IServiceCapableConnection) tempConn; 
	      // 调用客户端showMessage方法。 
	         sc.invoke("showMessage", new Object[]{clientName+" to All:"+sayWhat}); 
	      } 
	   } 
	   }else{ 
	     IConnection tempConn=onlineList.get(sayToName);     
	     if (tempConn instanceof IServiceCapableConnection) { 
	      IServiceCapableConnection sc = (IServiceCapableConnection) tempConn;     
	      sc.invoke("showMessage", new Object[]{clientName+" to "+sayToName+":"+sayWhat}); 
	      } 
	     IServiceCapableConnection sc = (IServiceCapableConnection) conn; 
	     sc.invoke("showMessage", new Object[]{clientName+" to "+sayToName+":"+sayWhat}); 
	   } 
	  } 
	// 用户断开连接的时候触发 
	  public void appDisconnect(IConnection conn) { 
	   String dis_user_id = conn.getClient().getId(); 
	   String user = (String) listSO.getAttribute(dis_user_id); 
	   // 根据ID删除对应在线纪录 
	   onlineList.remove(user); 
	   // 删除用户列表共享对象的对应属性 
	   listSO.removeAttribute(dis_user_id); 
	   IScope scope = Red5.getConnectionLocal().getScope(); 
	    Iterator it = scope.getConnections().iterator();  
	    for (;it.hasNext();) { 
	     Set connections = (Set)it.next(); 
	     IConnection tempConn = (IConnection)connections.iterator().next(); 
	     if (tempConn instanceof IServiceCapableConnection) { 
	         IServiceCapableConnection sc = (IServiceCapableConnection) tempConn; 
	       // 服务器端调用客户端flash方法。 
	         sc.invoke("disconnectMessage", new Object[]{user}); 
	      } 
	    } 
	  } 
		
		
}

 flex端代码

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
	<mx:Script>
		<![CDATA[
			import mx.collections.ArrayCollection;
			import mx.containers.HBox;
			import mx.controls.Alert;
			
			
			private var listSO:SharedObject;
			private var userArr:Array;
			private var conn:NetConnection;
			private var localUsername:String;
			[Bindable]
			private var cam:Camera;
			[Bindable]
			private var mic:Microphone;
			[Bindable]
			public var cards:ArrayCollection;
			public var videoUsers:Array;
			[Bindable]
			public var videoControlArr:Array;
			
			private var stm:NetStream;
			[Bindable]
			private var video_self:Video;
			
			protected function login(event:MouseEvent):void
			{
				localUsername = txt_name.text;
				if(localUsername== ""){
					Alert.show("用户名不能为空");
				}else{
					if(conn == null){
						conn = new NetConnection();
						conn.client = this;
						conn.addEventListener(NetStatusEvent.NET_STATUS,_statusHandler);
						conn.connect("rtmp://192.168.1.61/Red5ChatRoom",localUsername);
					}
				}
			}
			
			//状态监听
			private function _statusHandler(evt:NetStatusEvent):void
			{
				if(evt.info.code == "NetConnection.Connect.Success"){
					this.currentState = "chat";
					Alert.show("连接成功");
					video_clickHandler();
					this.showJoinInInfo(localUsername);
					_setListSO();
					
					
				}
				if(evt.info.code == "NetConnection.Connect.Failed"){
					Alert.show("连接失败");
				}
				if(evt.info.code == "NetConnection.Connect.Closed"){
					Alert.show("连接关闭");
				}
			}
			
			public function showJoinInInfo(message:String):void
			{
				conn.call("getOnloadUser",null,message);
			}
			
			public function result_getOnloadUser(str:String):void{
				txt_chatmsg.text += str + "加入聊天室" + "\n";
			}
			//创建用户列表共享对象
			private function _setListSO():void
			{
				listSO = SharedObject.getRemote("listSO",conn.uri,false);
				listSO.connect(conn);
				listSO.addEventListener(SyncEvent.SYNC,_listSOSyncHandler);
			}
			
			//用户列表共享对象被更新之后的事件
			private function _listSOSyncHandler(evt:SyncEvent):void{
				_showUserList();//更新用户列表
			}
			
			private function _showUserList():void
			{
				cards = new ArrayCollection(
					[{label:"All"}]
				);
				userArr = new Array();
				//用户数组更新
				for(var tmp:String in listSO.data){
					userArr.push(listSO.data[tmp]);
				}
				//添加到arrayCollection
				for(var i:int = 0; i<userArr.length;i++){
					cards.addItem({label:userArr[i]});
				}
				//将数组添加到列表数组中显示出来
				userList.dataProvider = cards;
				users.dataProvider = cards;
				addVideo(cards);
			}
			
			public function showMessage(message:String):void
			{
				txt_chatmsg.text += message + "\n";
			}
			
			protected function sendMessage(event:MouseEvent):void
			{
				var sendString:String = txt_yousay.text;
				var sendTo:String = userList.selectedItem.label;
				txt_yousay.text = "";
				conn.call("sayToAll",null,sendTo,sendString);
			}
			
			//断线通知
			public function disconnectMessage(disUser:String):void
			{
				txt_chatmsg.text += disUser+"退出聊天室\n";
			}
			//进入视频会议
			public function video_clickHandler():void
			{
				stm = new NetStream(conn);
				cam = Camera.getCamera();
				if(cam==null){
					Alert.show("没有可以使用的摄像头");
					return;
				}else{
					Security.showSettings(SecurityPanel.PRIVACY);
					cam.addEventListener(StatusEvent.STATUS,statusHandler);
					cam.addEventListener(ActivityEvent.ACTIVITY,activityHandler);
					cam.setLoopback(true);
					cam.setMotionLevel(50,100);
					cam.setMode(1280,960,15,true); 
					stm.attachCamera(cam);
				}
				mic = Microphone.getMicrophone();
				mic.addEventListener(StatusEvent.STATUS,micOnstatu);
				if(mic == null){
					Alert.show("没有可以使用的麦克风");
				}else{
					mic.setUseEchoSuppression(true);
					stm.attachAudio(mic);
				}
				stm.play("chinahrt-"+txt_name.text);
				stm.publish("chinahrt-"+txt_name.text,"live");
				video_self = new Video();
				video_self.width = 320;
				video_self.height = 240;
				video_self.attachCamera(cam);
				my_video.addChild(video_self);
				
			}
			
			private function micOnstatu(e:StatusEvent):void
			{
				mic.setLoopBack(true);
				mic.gain = 66;
				mic.rate = 11;
				mic.setUseEchoSuppression(true);
				mic.setSilenceLevel(1,-1);
			}
			
			private function statusHandler(e:StatusEvent):void
			{
				
			}
			
			private function activityHandler(e:ActivityEvent):void
			{
			
			}
			
			private function addVideo(cards:ArrayCollection):void
			{
				label1.text = "我的("+localUsername+")";
				myBox.removeAllChildren();
				var otherPerson:ArrayCollection = new ArrayCollection();
				for(var i:int=0;i<cards.length;i++){
					var o:Object = cards.getItemAt(i);
					if(o["label"]!=localUsername&&o["label"]!="All"){
						otherPerson.addItem(o);			
					}
				}
		//		Alert.show(otherPerson.length+"");
				var yushu:int = 0;
				var yushu:int= otherPerson.length%3;
				var rowNum:int = 0;
				var rowNum:int = otherPerson.length/3;
				
				if(yushu!=0){
					rowNum += 1;
				}
				if(yushu==0){
					for(var i:int=0;i<rowNum;i++){
						var hbox:HBox = new HBox();
						myBox.addChild(hbox);
						for(var ii:int=0;ii<3;ii++){
							var vbox:VBox = new VBox();
							hbox.addChild(vbox);
							var label:Label = new Label;
							label.text = otherPerson.getItemAt(i*3+ii)["label"];
							vbox.addChild(label);
							var videoDisplay:VideoDisplay = new VideoDisplay();
							videoDisplay.live = true;
							videoDisplay.width = 320;
							videoDisplay.height = 240;
							vbox.addChild(videoDisplay);
							var video:Video = new Video();
							video.width = 320;
							video.height = 240;
							var netStream:NetStream = new NetStream(conn);
							video.attachNetStream(netStream);
							netStream.play("chinahrt-"+label.text);
							
							videoDisplay.addChild(video);
						}
					}
				}else{
					for(var i:int=0;i<rowNum-1;i++){
						var hbox:HBox = new HBox();
						myBox.addChild(hbox);
						for(var ii:int=0;ii<3;ii++){
							var vbox:VBox = new VBox();
							hbox.addChild(vbox);
							var label:Label = new Label;
							label.text = otherPerson.getItemAt(i*3+ii)["label"];
							vbox.addChild(label);
							var videoDisplay:VideoDisplay = new VideoDisplay();
							videoDisplay.live = true;
							videoDisplay.width = 320;
							videoDisplay.height = 240;
							vbox.addChild(videoDisplay);
							var video:Video = new Video();
							video.width = 320;
							video.height = 240;
							var netStream:NetStream = new NetStream(conn);
							video.attachNetStream(netStream);
							netStream.play("chinahrt-"+label.text);
							videoDisplay.addChild(video);
						}
					}
					var hbox:HBox = new HBox();
					myBox.addChild(hbox);
					for(var i:int=0;i<yushu;i++){
						var vbox:VBox = new VBox();
						hbox.addChild(vbox);
					//	myBox.addChild(vbox);
						var label:Label = new Label();
						label.text = otherPerson.getItemAt((rowNum-1)*3+i)["label"];
						vbox.addChild(label);
						var videoDisplay:VideoDisplay = new VideoDisplay();
						videoDisplay.live = true;
						videoDisplay.width = 320;
						videoDisplay.height = 240;
						vbox.addChild(videoDisplay);
						var video:Video = new Video();
						video.width = 320;
						video.height = 240;
						var netStream:NetStream = new NetStream(conn);
					//	Alert.show(otherPerson.getItemAt((rowNum-1)*3+i)["label"]);
						video.attachNetStream(netStream);
						netStream.play("chinahrt-"+label.text);
						
						videoDisplay.addChild(video);
					}
				}
				
			}
		]]>
	</mx:Script>
	
	<mx:states> 
		<mx:State id="chatState" name="chat"> 
			<mx:SetProperty target="{form1}" name="width" value="0"/> 
			<mx:SetProperty target="{form1}" name="height" value="0"/> 
			<mx:SetProperty target="{form1}" name="x" value="0"/> 
			<mx:SetProperty target="{form1}" name="y" value="0"/> 
			<mx:AddChild position="lastChild"> 
				<mx:Panel x="10" y="10" width="381" height="370" layout="absolute" title="聊天信息"> 
					
					<mx:TextArea x="10" y="10" width="215" height="235" id="txt_chatmsg"/> 
					<mx:ComboBox x="233" y="34" width="118" id="userList"></mx:ComboBox> 
					<mx:Label x="233" y="11" text="用户列表"/> 
					<mx:DataGrid x="233" y="64" height="256" id="users" width="118"> 
						<mx:columns> 
							<mx:DataGridColumn headerText="用户名" dataField="label"/> 
						</mx:columns> 
					</mx:DataGrid> 
					<mx:TextInput x="10" y="253" height="67" width="150" id="txt_yousay"/> 
					<mx:Button x="168" y="253" label="发送" width="57" click="sendMessage(event)"/> 
				<!--	<mx:Button x="168" y="298" label="进入视频会议" width="57" click="video_clickHandler(event)"/>--> 
				</mx:Panel> 
			</mx:AddChild> 
			<mx:AddChild position="lastChild"> 
				<mx:VideoDisplay live="true" x="10" y="410"  width="320" height="240" id="my_video"/> 
			</mx:AddChild> 
			<mx:AddChild position="lastChild"> 
				<mx:Label id="label1" x="10" y="390" text="我的"/> 
			</mx:AddChild> 
			<!--<mx:AddChild position="lastChild"> 
				<mx:VideoDisplay live="true"  x="399" y="224"  width="320" height="240" id="other_video"/> 
			</mx:AddChild> 
			<mx:AddChild position="lastChild"> 
				<mx:Label x="399" y="198" text="对方的"/> 
			</mx:AddChild> -->
			<mx:AddChild position="lastChild">
				<mx:VBox id="myBox" x="399" y="10"/>
			</mx:AddChild>
		</mx:State> 
	</mx:states> 
	
	<mx:Form x="10" y="10" width="283" height="126" id="form1"> 
		<mx:FormItem label="用户名:"> 
			<mx:TextInput id="txt_name"/> 
		</mx:FormItem> 
		<mx:FormItem> 
			<mx:Button label="登陆" click="login(event)"/> 
		</mx:FormItem> 
	</mx:Form> 
</mx:Application>

 百度网盘:http://pan.baidu.com/s/1hqkgBly

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
package chat; import org.red5.server.adapter.ApplicationAdapter; import org.red5.server.api.IConnection; import org.red5.server.api.IClient; 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; import org.red5.server.api.ScopeUtils; import org.red5.server.api.so.ISharedObjectService; import org.red5.server.api.*; import org.red5.server.api.scheduling.*; import org.red5.samples.components.ClientManager; import org.red5.server.api.service.ServiceUtils; import org.red5.server.api.service.*; import org.red5.server.api.service.IPendingServiceCallback; // import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.util.*; // // public class Application extends ApplicationAdapter{ public Map<String, CClient> clients = new HashMap<String, CClient>(); public class CClient{ String id = null; String pseudo = null; String role = null; String sexe = null; String status = null; String room=null; String world=null; public String getRole(){ return role; } public String getName(){ return pseudo; } public String getId(){ return id; } public String getSexe(){ return sexe; } public String getStatus(){ return status; } public String getRoom(){ return room; } public String getWorld(){ return world; } public void setRole(String _role){ role = _role; } public void setPseudo(String _pseudo){ pseudo = _pseudo; } public void setSexe(String _sexe){ sexe = _sexe; } public void setId(String _id){ id = _id; } public void setStatus(String _status){ status = _status; } public void setRoom(String _room){ room = _room; } public void setWorld(String _world){ world = _world; } }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值