在这里首先要感谢一下 http://blog.csdn.net/boy_jiaojian/article/details/6631589 网友的一篇文章,这篇文章写的很好,使我在开始接触学习red5的过程中受到了很大的启发。
接触Flex和java通信有一段时间了,但是在这个过程中有一点不爽,用Flex做客户端的一个缺点是当用户点击了浏览器右上角的 关闭 按钮时,在服务器端是检测不到的,所以就产生了无法实时统计客户端在线数量的问题,虽然有人说可以在服务器端使用 HttpSessionListener进行监听,但是也只能是在flex连接客户端的时候创建Session,当flex断开的时候不会立刻去执行sessionDestroyed()方法,而是在超过了Session设置的时间后才会执行sessionDestroyed()方法,默认的是30分钟(可以修改),这样就无法准确统计客户端在线数量。为此找到了red5,其中的appConnect()和appDisconnect()可以准确捕捉到Flex的连接和关闭。现在就开始步骤:
首先是选择red5的版本,目前出到了1.0RC,但是本人觉得0.8的版本比较稳定,下载地址:http://code.google.com/p/red5/
从网上下载两个东西:red5-war-0.8.0.zip 和 setup-Red5-0.8.0.exe,red5-war-0.8.0.zip解压之后有两个文件ROOT.war和Red5 War.pdf其中Red5 War.pdf是帮助文档,里面全是英文,看不懂,不过已经有人翻译过了,虽然不是太准确,还是能大概看懂意思。
1:安装 setup-Red5-0.8.0.exe(C:\Program Files\Red5);
2:删除你tomcat重conf里面的catalina文件件,删除work文件夹,删除webapps\ROOT文件夹(因为这里的两个文件夹都是tomcat的,现在你要集成red5,所以删掉,当你配置完,所有后重启tomcat时这两个文件会重新的生成);
3:找到你的tomcat的webapps,然后将ROOTwar包放在webapps下,(将webapps下的root文件夹命名为root_old,因为一会重启tomcat时会解压ROOTwar,重新生成新 的root文件夹);
4:重启tomcat;
5:打开tomcat下webapps\ROOT\WEB-INF\classes,里面的root-web.xml.将里面的所有端口都换成8080,PS:现在看来该这里东西对我们以后写的项目也没影响,该它只是为了访问red5主页或者它里面的例子。
6.再重启tomcat,现在在浏览器中输入:http://localhost:8080 如果出现red5的主页,而不 是以往 我们熟知的tomcat主页就行了。
现在下面的才是真正我们需要的东西:
新建java web项目,命名为red5Server:
7:我们来到0.:8windows安装版的安装路径下找到red5.jar 把它拷工程的lib下,同时你也去tomcat的root文件夹下的classes里面 的lib的所以jar拷的你工程的lib下 同时你也去tomcat下找到Root文件夹,里面的web-inf下的classes里面的配置文件,将所有文件拷到你工程src下,将tomcat6\webapps\ROOT\WEB-INF下的web.xml 和log4j的配置文件拷到你的项目的web-inf下,覆盖以前的文件。到这里,你的项目基本快要完成了,接下来就是修改里面的 配置。
样子如图:
现在你就要新建一个包了:
前面那两 个包你们不用管,主要是red5.example.red5Server这个包,里面建个类:
import org.red5.server.adapter.ApplicationAdapter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
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;
public class Application extends ApplicationAdapter {
private String userName;
//客户端调用的方法
public String callFromClient(String userName) {
System.out.println("ddd");
this.userName = userName;
callClient();
return "Hello:"+userName;
}
//服务器端调用客户端的方法
public void callClient() {
IConnection conn=Red5.getConnectionLocal();
if (conn instanceof IServiceCapableConnection) {
IServiceCapableConnection sc = (IServiceCapableConnection) conn;
sc.invoke("callFromServer", new Object[]{"hi,"+userName+" this message from server"});
}
}
}
首先要改的就是web.xml,容器从这里找到你的服务,
将web.xml中的
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>/</param-value>
</context-param>
改成
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>/red5Server</param-value>
</context-param>
然后在src建立以个red5Server.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="web.context.red5Server" class="org.red5.server.Context">
<property name="scopeResolver" ref="red5.scopeResolver" />
<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.red5Server" />
<property name="handler" ref="web.handler.red5Server" />
<property name="contextPath" value="/red5Server" />
<property name="virtualHosts"
value="*,localhost, localhost:8080, 127.0.0.1:8080" />
</bean>
<bean id="web.handler.red5Server"
class="red5.example.red5server.Application" />
< /beans>
想必你们也能明白这里的意思了。
然后这里就非常的重要了,打re5-core.xml,找到里面的:
<bean id="rtmpTransport" class="org.red5.server.net.rtmp.RTMPMinaTransport" init-method="start" destroy-method="stop">
<property name="ioHandler" ref="rtmpMinaIoHandler" />
<property name="address" value="10.30.6.221" />
<property name="port" value="8080" />
<property name="receiveBufferSize" value="65536" />
<property name="sendBufferSize" value="271360" />
<property name="eventThreadsCore" value="4" />
<property name="eventThreadsMax" value="8" />
<property name="eventThreadsQueue" value="-1 " />
<property name="eventThreadsKeepalive" value="60" />
</bean>
首先要改的就是web.xml,容器从这里找到你的服务,
将web.xml中的
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>/</param-value>
</context-param>
改成
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>/red5Server</param-value>
</context-param>
然后在src建立以个red5Server-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="web.context.red5Server" class="org.red5.server.Context">
<property name="scopeResolver" ref="red5.scopeResolver" />
<property name="clientRegistry" ref="global.clientRegistry" />
<property name="serviceInvoker" ref="global.serviceInvoker" />
<property name="mappingStrategy" ref="global.mappingStrategy" />
</bean>
<bean id="web.scope.red5Server" 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.red5Server" />
<property name="handler" ref="web.handler.red5Server" />
<property name="contextPath" value="/red5Server" />
<property name="virtualHosts"
value="*,localhost, localhost:8080, 127.0.0.1:8080" />
</bean>
<bean id="web.handler.red5Server"
class="red5.example.red5server.Application" />
< /beans>
然后这里就非常的重要了,打re5-core.xml,找到里面的:
<!-- RTMP Mina Transport -->
<bean id="rtmpTransport" class="org.red5.server.net.rtmp.RTMPMinaTransport" init-method="start" destroy-method="stop">
<property name="ioHandler" ref="rtmpMinaIoHandler" />
<property name="connectors">
<list>
<bean class="java.net.InetSocketAddress">
<constructor-arg index="0" type="java.lang.String" value="192.168.1.192" />
<constructor-arg index="1" type="int" value="5081" />
</bean>
<!-- You can now add additional ports and ip addresses
<bean class="java.net.InetSocketAddress">
<constructor-arg index="0" type="java.lang.String" value="0.0.0.0" />
<constructor-arg index="1" type="int" value="1936" />
</bean>
-->
</list>
</property>
<property name="receiveBufferSize" value="65536" />
<property name="sendBufferSize" value="271360" />
<property name="eventThreadsCore" value="4" />
<property name="eventThreadsMax" value="8" />
<property name="eventThreadsQueue" value="-1 " />
<property name="eventThreadsKeepalive" value="60" />
<!-- This is the interval at which the sessions are polled for stats. If mina monitoring is not
enabled, polling will not occur. -->
<property name="jmxPollInterval" value="1000" />
<property name="tcpNoDelay" value="true" />
</bean>
将其中的
<constructor-arg index="0" type="java.lang.String" value="192.168.1.192" />
<constructor-arg index="1" type="int" value="5081" /> 修改为自己所要监听的服务器的IP地址和端口号,(一会会说为什么修改成5081);
下面写前台吧,我用Flex
<?xml version="1.0" encoding="utf-8"?>
< mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="init()">
<mx:Script>
<![CDATA[
import flash.net.*;
import flash.events.*;
import flash.utils.*;
import mx.controls.*;
private var nc:NetConnection;
public function connServer():void {
nc = new NetConnection();
nc.addEventListener(NetStatusEvent.NET_STATUS, netStatus);
nc.addEventListener(SecurityErrorEvent.SECURITY_ERROR, netSecurityError);
nc.connect(txtServerURL.text,txtUserName.text);
}
public function init():void {
// Alert.show("页面初始化完成!")
nc = new NetConnection();
nc.addEventListener(NetStatusEvent.NET_STATUS, netStatus);
nc.addEventListener(SecurityErrorEvent.SECURITY_ERROR, netSecurityError);
nc.connect("rtmp://192.168.1.192:5081/red5Server");
nc.client = this;
//Alert.show("连接完成");
}
private function netStatus(event:NetStatusEvent):void {
var connStatus:String = event.info.code;
Alert.show(connStatus);
if(connStatus == "NetConnection.Connect.Success") {
txtResult.text += "登陆成功";
nc.call("callFromClient",new Responder(callServerMethodResult,callServerMethodFault),Math.random().toString());
}
else if(connStatus == "NetConnection.Connect.Rejected")
{
//登录被拒绝
txtResult.text += event.info.application;
}
else if(connStatus == "NetConnection.Connect.Failed")
{
//登录被拒绝
txtResult.text += event.info.application;
}
}
private function netSecurityError(event:SecurityErrorEvent):void {
Alert.show("netSecurityError: " + event);
}
public function callServerMethodResult(re:String):void {
Alert.show("客户端调用服务器端方法成功,返回结果:"+re);
}
public function callServerMethodFault(fo:Object):void {
Alert.show("客户端调用服务器端方法失败:"+fo.toString());
}
public function callFromServer(re:Object):void {
Alert.show("服务器端调用客户端方法,传递的参数为:"+re.toString());
}
]]>
</mx:Script>
<mx:Label x="10" y="38" text="输入用户名:"/>
<mx:TextInput x="83" y="36" id="txtUserName" width="167"/>
<mx:Label x="10" y="10" text="连接的服务器:"/>
<mx:TextInput x="83" y="8" id="txtServerURL" text="rtmp://10.30.6.221:8080/red5Server"/>
<mx:Button x="10" y="64" label="连接到red5服务器" width="240" click="this.connServer()"/>
<mx:TextArea x="10" y="94" width="240" height="154" id="txtResult"/>
</mx:Application>
这个项目要映射到你的J2EE项目的目录下,比如这里我是映射到red5Server下,输入路径为/red5Server/chart
(事实上只要建一个Flex项目粘贴上面代码,运行就可以了,不一定非要映射到red5Server下);
下面是我学习red5之后测试得到的总结:
总结1:关于刷新:每次client端进行一次刷新,则server端就断开一次连接,然后再进行连接;
总结2:关于跳转:如果是覆盖了之前的页面,则之前的连接断开,进行新的连接,如果是又打开了一个新的页面,则原有的连接不断开;总结:如果是使用NetConnection进行对red5的连接,则连接是面向单个页面的,页面消失了,则连接也消失了,刷新也是如此;
总结3:将red5整合到tomcat中时会遇到一个问题,将red5的监听端口也设置成8080(和tomcat一样)时,在本机上测试是没有问题的,但是在其他电脑上登录就不行了,无法登录,其原因可能是他们共同监听了一个端口,如果异地登录的话,red5对其监听进行处理,那么tomcat就失去了作用;刚开始我修改了red5Server-web.xml文件和root-we.xml文件中的端口号为5080但是没有修改red5-core.xml文件,还是报错,通过测试,找到了其解决方法:
找到red5-core.xml文件,找到其中的
<bean id="rtmpTransport"class="org.red5.server.net.rtmp.RTMPMinaTransport"init-method="start" destroy-method="stop">
<propertyname="ioHandler" ref="rtmpMinaIoHandler" />
<property name="connectors">
<list>
<beanclass="java.net.InetSocketAddress">
<constructor-argindex="0" type="java.lang.String"value="192.168.1.192" />
<constructor-argindex="1" type="int" value="5081" />
</bean>
<!-- You can now addadditional ports and ip addresses
<bean class="java.net.InetSocketAddress">
<constructor-argindex="0" type="java.lang.String" value="0.0.0.0"/>
<constructor-argindex="1" type="int" value="1936" />
</bean>
-->
</list>
</property>
<propertyname="receiveBufferSize" value="65536" />
<propertyname="sendBufferSize" value="271360" />
<propertyname="eventThreadsCore" value="4" />
<propertyname="eventThreadsMax" value="8" />
<propertyname="eventThreadsQueue" value="-1 " />
<propertyname="eventThreadsKeepalive" value="60" />
<!--This is the interval at which the sessions are polled for stats. If minamonitoring is not
enabled,polling will not occur. -->
<propertyname="jmxPollInterval" value="1000" />
<propertyname="tcpNoDelay" value="true" />
</bean>
注意红色的部分,将原有的8080端口修改为其他端口,如果本机上还安装有red5的安装版但是并未启动,也不适合将端口号设置为5080。具体原因不详。于是修改成了5081,在其他电脑上测试也没有问题了。(疑问:只是修改了red5-core.xml文件文件就可以通过测试了,那两个文件修改不修改都一样,是否修改了更好呢?)
总结4:关于服务器端使用SharedObject的注意事项:
在服务器端建立SharedObject:
this.createSharedObject(scope,"chart", true);//第三个参数true:持久的;false:临时的;