今天研究了一下FluorineFx下如何实现rtmp协议的应用开发,从网上找了一些文章和资料,照着做发现是碰到了不少问题。不过到最后还是被我解决了,因此写下这篇文章一来怕自己以后给忘了,二来让其他遇到同样问题的朋友们提供一个参考。
其实要实现rtmp协议很简单,先来说说服务器端的操作步骤,首先使用Visual Studio创建一个新项目FluorineFxASP.NET网站(本人使用的是VS2010,顺便说一下FluorineFx在VS2010下没有项目模板,不过网上有人自己制作了一个项目模板,前提是你要先安装FluorineFx然后再安装他的模板即可制作FluorineFx相关应用了。需要的朋友可以到这里下载:http://www.dotblogs.com.tw/ouch1978/archive/2010/11/11/fluorinefxtemplate.aspx?fid=22774)。然后再添加一个FluorineFxServiceLibrary项目。如下图所示:
然后再FlashRemotingServiceLibrary中添加一个作为实现rtmp协议的应用类MyRtmpApp.cs。如同:
这里要注意的是,MyRtmpApp类需要继承FluorineFx.Messaging.Adapter.ApplicationAdapter否则无法正常运行。然后为MyRtmpApp类写上客户端连接事件处理,代码如下:
publicoverridebool AppConnect(FluorineFx.Messaging.Api.IConnection connection, object[]parameters)
{
return true;
}
这里只是作为演示,因此不需要作任何验证用户身份的处理,直接返回true则表示接受客户端连接。完成这一步后,接下来就是更改服务器端配置的工作了,打开网站中的WEB-INF/flex/services-config.xml配置文件。在channels节点下添加多一个channel-definition节点用于开启rtmp协议处理功能(事实上配置文件中已存在此配置只是将其注释掉了,只要把注释符去掉即可)。配置完成后的配置文件内容如下图:
记住上面配置的rtmp端口2037,因为在客户端连接时需要指定到该端口才能访问到应用(如果你的2037端口被其他应用占用可以设置到其他端口上)。接下来在网站下添加文件夹apps,在apps中再添加文件夹MyRtmpApp(此文件夹的名称最好和你定义的应用类名称相同),最后在MyRtmpApp文件夹中添加配置文件app.config,文件内容如下图所示:
这里要注意的是app.config配置文件中的application-handler节点中的type属性一定准确地填上刚才创建的应用类的全限定名称(包含名称空间)。否则可能导致无法正常运行。
服务端的工作就暂且告一段落了,先来写一个客户端的程序来访问一下看能够正常连接。客户端的代码如下所示(我使用的是FlexBuilder4.5作为开发环境):
var request:URLRequest = new URLRequest("http://localhost/Gateway.aspx");
var loader:URLLoader = new URLLoader(request);
loader.addEventListener(Event.COMPLETE, loaderCompleteHandler);
private function loaderCompleteHandler(event:Event):void{
var connect:NetConnection()=new NetConnection();
connect.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
connect.connect("rtmp://localhost:2037/MyRtmpApp","");
connect.client=this;
}
private function netStatusHandler(event:NetStatusEvent):void{
trace(event.info);
}
整段代码中最值得注意的是我是先调用了站点的Gateway.aspx页面等待成功后再进行MyRtmpApp的应用连接的。为什么这样做呢?网上的资料都没有说到这个问题,之前由于我没有调用这个页面导致我一直连接失败,在偶然的一次调试中发现连接成功,后来在IIS上经过多次的验证发现如果站点处未激活状态下(也就是说w3wp这个进程没有启动的时候)直接进行应用的连接请求是会导致连接失败的。这也说明了.net环境下的rtmp需要依靠IIS中的进程服务来维持(不像FMS那样专门有一个服务来处理)。连接成功后会在event的info属性中返回。Info的属性列表如下图:
既然连接成功,接下来就可以与服务器端进行通讯了,为了让大家可以了解更加透彻,我会从客户端连接成功后调用服务器端的一个名叫Say的方法,然后服务器端在这个方法里面调用客户端的一个receiveContent的方法来让客户端收到自己发送的消息。把上面的客户端代码改了一下,如下所示:
varrequest:URLRequest=newURLRequest("http://localhost/Gateway.aspx");
varloader:URLLoader=newURLLoader(request);
loader.addEventListener(Event.COMPLETE,loaderCompleteHandler);
private function loaderCompleteHandler(event:Event):void{
var connect:NetConnection = new NetConnection();
connect.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
connect.connect("rtmp://localhost:2037/MyRtmpApp","");
connect.client=this;
}
private function netStatusHandler(event:NetStatusEvent):void{
var connect:NetConnection = event.target as NetConnection;
trace(event.info);
if(event.info.code == "NetConnection.Connect.Success"){
//调用服务端方法
connect.call("Say",connect as flash.net.Responder,"Hello world!");
}
}
public function receiveContent(content:String):void{
trace("receive :"+content);
}
服务器端代码如下:
publicvoid Say(string content)
{
IServiceCapableConnection connection = FluorineContext.Current.Connection as IServiceCapableConnection;
if(connection != null)
{
connection.Invoke("receiveContent", newobject[]{content}, this);
}
}
public void ResultReceived(IPendingServiceCall call)
{
}
服务器端的MyRtmpApp需要实现IpendingServiceCallback接口,此接口用于监听客户端方法返回委托ResultReceived。
在FB中测试,可以看到控制台中输出receive :Hello world!字符串。那就证明测试成功了。