代理共享对象的使用

:em26: chat Union站点开发过程中,碰到在线列表问题:

在主持人方面,应该能够看到自己房间中的所有客人;而在客人方面,应该能够看到自己所在房间的客人,同时也能看到所有在线的主持人一方便切换房间。对于这个功能,我打算这样实现:

  • 每个主持人房间是一个应用程序实例,都有自己的共享对象(SO),保存自己房间中的在线用户名称。当用户注销或离开,就更新SO并通知当前主持人和所有在此房间中的客人更新自己的在线列表。
  • 而对于主持人在线列表,则不能放在主持人自己的房间中。因为所有的客人都是共享同一个主持人在线列表的,而这些客人可能处于不同的房间之中。我考虑在应用程序中使用一个单独的(common)实例保存所有主持人的在线状态,所有的客人都需要连接到online实例来获取主持人在线状态

对于这个设计,我首先想到的是使用两个NetConnection,一个连到主持人房间实例,一个连接到common实例,但是这样的设计未免麻烦,两个NetConnection都要监视连接状态,增加了客户端程序的复杂性。
突然想到代理共享对象(proxy shared object),使用它,连接到common实例的工作就可以交给服务器端,与客户端无关了。
以下是main.acs的内容:

 1application.onAppStart = function(){
 2nc = new NetConnection();
 3nc.connect("rtmp://localhost/proxy/common");
 4nc.onStatus = function(e){
 5trace(e.code+" - "+e.description);
 6}
 7so = SharedObject.get("proxy",true,nc);
 8so.onSync = function(e){
 9trace("so更新事件:"+e[0].code);
10}
11so.onStatus = function(e){
12trace("so状态事件:"+e.code);
13}
14}

需要注意的一点,是nc.connect("rtmp://localhost/proxy/common");,这里的连接地址必须是绝对路径。我最早的尝试是rtmp:/proxy/common,结果是不能连接成功。
以下是客户端的脚本:

1nc = new NetConnection();
2nc.connect("rtmp://localhost/proxy/room1");
3myso = SharedObject.getRemote("proxy", nc.uri, true);
4myso.connect(nc);

一开始我犯了一个错误,认为客户端连接的共享对象应该是服务器端的代理共享对象的实例名称,因此我的连接语句是这样

1myso = SharedObject.getRemote("so", nc.uri, true);

结果在app Inspector面板中发现有proxy/room1实例中竟然有两个共享对象,一个是so,一个是proxy。其实,客户端连接的共享对象应该与服务器端连接的共享对象名称相同。

测试后发现,虽然服务器提示nc连接成功,但是却看不到共享对象被写入。郁闷了好长时间,考虑了多种情况,最后发现问题在于是代理共享对象所在的应用程序与“雇主”所在的应用程序是同一个。其实早就该想到这点,帮助文档中虽然没有明确强调,但是也已经指明了。

将main.asc代码改为如下所示,可以看到“雇主”的共享对象被代理共享对象写入了。

1application.onAppStart = function(){
2......
3nc.connect("rtmp://localhost/proxy1/common");
4......
5}