Red5研究
来源:互联网 发布:蜻蜓fm收音机mac版 编辑:程序博客网 时间:2024/05/22 17:16
最近因为工作需要:将从DVR得到的视频通过网页的flash player插件来直播。
要完成这个任务,首先必须对基于RTMP的流媒体服务器有一定的了解。以前我有花了一段时间学Flash Media Server,不过因为FMS卖得很贵,所以还是用免费的Red5好了。
下面开始介绍Red5:
Red5是建立在Jetty(servlet engine) , Mina (networking)基础之上的,参考了Terracotta Clustering技术理念,并通过使用Spring框架将起整合起来的。
Jetty是一款运行速度较快轻量级的开源servlet 容器,可以作为嵌入式服务使用。
Mina 是Apache组织下的一个基于 Java NIO 技术的新项目,它为开发高性能和高可用性的网络应用程序提供了非常便利的框架。
Terracotta是开源的Java集群技术。
Spring是轻量级Java企业级开发的事实标准,Red5采用Spring来管理使程序逻辑更加清晰,耦合性更低,扩展性更好。
Red5响应请求的流程
(1)Red5在启动时会调用RTMPMinaTransport的start()方法,该方法会开启rmtp的socket监听端口(默认是1935),然后使用Mina 的api 将RTMPMinaIoHandler 绑定到该端口。
(2)RTMPMinaIoHandler 上定义了messageReceived()、messageSent()、sessionOpened()和sessionClosed()等方法,当有socket请求时,相应的方法会被调用。这时RTMPMinaIoHandler 会使用当前的socket连接来创建一个(或者使用之前创建好的)RTMPMinaConnection,并将其作为参数传递给定义于RTMPHandler类上的相应的messageReceived()、messageSent()、connectionOpened()和connectionClosed()方法。
(3)RTMPHandler会调用Server类的lookupGlobal()方法获得当前的GlobalScope,然后再利用GlobalScope找到当前socket请求应该使用的WebScope(这个WebScope 由开发者在WEB-INF\red5-web.xml中定义)。最后,RTMPHandler会调用RTMPMinaConnection 的connect ()方法连接到相应的WebScope。
(4)通常来说,WebScope又会将请求转移给ApplicationAdapter,由它来最终响应请求,而项目中通过重载ApplicationAdapter的方法来实现自己的逻辑。至此,控制流进入了开发者的项目中。
ApplicationAdapter类介绍
MultiThreadedApplicationAdapter类,是Red5应用程序的基础类。它提供了操作SharedObjects 和 streams的方法,还有连接和服务列表,是一个应用程序基本的Iscope。它实现了IstreamAwareScopeHandler接口,提供了在应用程序种控制流的方法。它还提供了一个很有用的事件控制器,可以拦截流、授权用户访问等。可以在其子类中添加各种方法,在客户端上通过NetConnection.call()方法调用服务器端的方法。这与Flash Media Server不同,FMS需要将你的客户端方法保存在服务器端,Red5提供更方便的方式进行远程方法调用。
ApplicationAdapter类是MultiThreadedApplicationAdapter的子类。ApplicationAdapter使用单线程的方式进行方法调用的消息出来,所以其性能不如MultiThreadedApplicationAdapter。
这2个类的核心方法为:
public boolean appStart(IScope arg0):Red5应用程序启动时自动执行此方法,进行一些参数初始化,如声明连接数据库的资料等。
public void appStop(IScope arg0):Red5应用程序停止时自动执行此方法。
public boolean appConnect(IConnection arg0, Object[] arg1):当客户端连接本应用程序时自执行此方法。
public boolean appDisconnect(Iconnection conn):当客户端断开连接时自动执行此方法。(如关闭浏览器、关闭FLASH PLAYER等特殊情况,均会触发该方法)。
public boolean appJoin(IClient arg0, IScope arg1):当有新的连接加入进来时自动调用。
获取某客户在服务器端保留/设置的变量:首先要通过Red5.getConnectionLocal()方法获得Iconnection对象,然后调用它的getClient()方法获得Client对象,再通过Client对象的getAttributes(“var_name”) 方法获得对应的变量的值。
下面是继承ApplicationAdapter类实现自己的Red5应用程序的代码例子:
import org.red5.server.adapter.ApplicationAdapter;
import org.red5.server.api.IClient;
import org.red5.server.api.IConnection;
import org.red5.server.api.IScope;
public class Application extends ApplicationAdapter
{
@Override
public boolean appStart(IScope arg0) // 应用程序启动时自动执行
{
return super.appStart(arg0);
}
@Override
public void appStop(IScope arg0) // 应用程序停止时自动执行
{
super.appStop(arg0);
}
@Override
public boolean appConnect(IConnection arg0, Object[] arg1) // 客户端连接本应用程序时自执行
{
if(arg1 != null){
for(Object o:arg1){
…
}
}
return super.appConnect(arg0, arg1);
}
@Override
public boolean appJoin(IClient arg0, IScope arg1) // 有新的连接加入进来时自动调用
{
//client.setAttribute("username",username);
//IConnection current = Red5.getConnectionLocal();
//current.getClient().getAttribute("username")
//Iterator<IConnection> it=appScope.getConnections();
//var nc:NetConnection=new NetConnection();
//nc.connect("rtmp://127.0.0.1/your_app","your_vars");
return super.appJoin(arg0, arg1);
}
}
主要API简介
Red5提供了很多接口供开发人员进行二次开发:
IConnection:连接对象。每个连接都有一个关联的客户端和域。连接可能是持续型、轮询型、或短暂型。建立此接口的目的,是为了给不同的子类,如 RTMPConnection,RemotingConnection,AJAXConnection, HttpConnection 等,提供基础通用的方法。它提供getClient()方法来获取客服端对象。
IScope :每个Red5应用程序至少有一个域,用来搭建处理器、环景、服务器之间的连接。域可以构成树形结构,所有客户端都可以作为其节点共享域内的对象(比如流和数据)。所有的客服端(client)通过连接(connection)连接到域中。对于单一域,每个连接对应一个客服端,每个客服端对应一个id,简单的应用,操作就针对一个id和一个连接进行。
IServiceCapableConnection :获取有效连接。代码中先获取到连接实例,然后判断是否是有效连接并强制类型转换,之后调取客户端相应函数。
IClient :客户端对象代表某单一客户端。一个客户端可以和同一主机下不同的域分别建立连接。客户端对象和HTTP session 很相像。可以使用IClientRegistry.newClient(Object[])方法来创建IClient对象。
ApplicationAdapter:ApplicationAdapter是应用层级的IScope。若要处理流进程,需实现 IStreamAwareScopeHandler接口中的相应处理方法。ApplicationAdapter还提供了有效的事件处理机制,来进行截取流、确认用户等操作。同时,其子类中引入的方法均可在客户端通过 NetConnection 调取。在Aodbe 的FMS 中必须在服务器端维护客户端对象,与之相较,Red5 为您的远程请求提供了更加方便快捷的操作方法。
Red5开发示例
开发一个Red5 应用的服务器项目,和一般的J2EE 程序相似。进入Red5的webapps目录下,参考doc/templates目录下的myapp 文件夹,新建一个以自己项目命名的文件夹,比如myFirst,并对配置文件做相应的修改。然后开始编写自己的服务器端程序:
public class MyApplication extends ApplicationAdapter
{
private IScope appScope;
private String username=””;
// 取得本次连接的Iscope, appStart方法在连接开始时自动触发
public boolean appStart(IScope app)
{
appScope = app;
return true;
}
// 连接时触发的函数,定义本过程中的username
public boolean appConnect(IConnection conn, Object[]params)
{
username = (String)params[0];
return true;
}
// 连接加入时触发的函数,写入username的值
public boolean appJoin(IClient client, IScope app)
{
client.setAttribute(”username”,username);
return true;
}
// 客户端登录时调用函数,将返回目前登录的在线列表
public String login()
{
IConnection current = Red5.getConnectionLocal();
System.out.println(”<—”+current.getClient().getId()+”:”
+current.getClient().getAttribute(”username”));
return getOnlineList();
}
// 取得在线列表,对在线的客户端进行遍历,并显示。
public String getOnlineList()
{
Iteratorit=appScope.getConnections();
StringonLineList=””;
while(it.hasNext())
{
IConnectionthis_conn=it.next();
IClientic=this_conn.getClient();
Stringu=ic.getAttribute(”username”).toString();
onLineList+=ic.getId()+”,”+u+”;”;
System.out.println(u);
}
return onLineList;
}
我们还需要对刚刚完成的程序进行配置,编辑WEB-INF下的red5-web.xml,增加<bean id=”web.handler” class=”MyApplication”>这样本程序将以刚才写的Application来运行。编辑web.xml,找到webAppRootKey,将其下面的paramvalue标签中的值修改为/myFirst,编辑red5-web.properties,将第一句修改为webapp.contextPath=/myFirst。
这样,在客户端中就可以轻易的调用login()方法了。在FLASH 中新建一个文件,输入以下代码:
nc = new NetConnection();
nc.connect(”rtmp:// localhost/myFirst”);
nc.onResult = function(obj)
{
trace(obj);
}
nc.call(”login”,nc);
客户端登录服务器,需要调用login方法,服务器便能得到一份客户端的在线列表了。
- Red5研究
- Red5研究
- red5研究日记
- Red5源码研究一
- Red5源码研究一
- Red5研究之了解Mina
- Red5源码研究二-RTMP规范(握手)
- red5
- red5
- Red5
- red5
- 关于Red5研究的文章分享(入门)
- Red5源码研究二-RTMP规范(协议栈)
- 一种改进的red5集群方案的应用、基于Red5服务器集群负载均衡调度算法研究
- Red5源码研究二-RTMP规范(传输层Chunk Stream Protocol)
- 流媒体视频直播类研究(一):Windows环境下部署Red5-Server流媒体服务器
- 分享一下最近对直播的研究red5 nginx-rtmp-module rtmp hls m3u8 ts
- Red5 FAQ
- Activity 的属性之android:screenOrientation
- SQL中EXISTS的用法
- 关于int全区变量读写的原子性
- tomcat多个端口的使用
- 浅谈堆
- Red5研究
- 动态获取当前时间显示
- Centos 5.x RHEL 5.x 安装salt升级Zmq2.x 到Zmq4.x
- 主程的晋升攻略(6):CGI和FastCGI
- Josephus约瑟夫问题及其变种
- 世界互联网大会今日开幕 亮点揭秘
- jquery easy ui 新弹出的dialog 每次都显示第一次load的数据
- Dimension screen=Toolkit.getDefaultToolkit.getScreenSize();//获取屏幕尺寸对象
- Java关键字final、static使用总结