red5 remote ShareObject

原文鏈接

 

ShareObject 主要用途

 

SharedObjects (SOs)  主要用於多客戶端的實時數據同步和方法統一調用。SharedObject 是一個遠程的對象能夠被多個客戶端共享,也就說這些客戶端在同一個域(scope)裏面。

 

 什麼是 scope?

你可以把scope 當作一個聊天室,這個聊天室是通過URI 鏈接到服務器

例如:rtmp://localhost/red5test/lobby

"red5test"  是application 域(scope) 

"lobby" 是聊天室作用域,也即 "red5test" 子域

 

 

客戶端代碼的編寫

 

客戶端可以用下面的代碼獲得 SharedObject  連接:

 

// at first you need to establish a connection to the server of course
nc = new NetConnection();
nc.connect( "rtmp://localhost/red5test/", true );

// when the NetConnection is successfully established
// (you have to listen to NetStatusEvent.NET_STATUS event)
// you can connect to a remote SharedObject e.g. named "chat"
so = SharedObject.getRemote("chat", nc.uri, false);

// when the connection to the SO is successfully established,
// you can begin to specify its contents
so.setProperty("message","hello to all");

 

red5 處理 ShareObject 過程

當客戶端程序連接到SharedObject,red5就會查找指定作用域SharedObject是否存在(例如上面程序“chat”).如果存在,red5就會重用它;如果不存在,red5 就會在該作用域下創建新的SharedObject提供客戶端使用。

當最後一個客戶端從該作用域斷開連接,SharedObject就會被銷燬(at least for non-persistent ones)。

 

服務端 ShareObject  處理過程

a)服務端獲取 SharedObject

也可以從服務獲取 SharedObject ,例如,服務端可以對SharedObject 做改動,讓後把這些改動以廣播的方式傳遞給客戶端

在你的 java程序中你可以用如下的代碼檢查SharedObject 的存在

//get scope of the current connection first
IScope scope = Red5.getConnectionLocal().getScope();
// get SO
ISharedObject so = getSharedObject(scope, "chat");

 b)服務端創建 SharedObject

當room 創建後,就可以創建新的 SharedObject 了,方法是覆寫 ApplicationAdapter  roomStart 的 roomStart  方法,代碼如下:

 

public class SampleApplication extends ApplicationAdapter {

  public boolean roomStart(IScope room) {
      if (!super.roomStart(room))
          return false;

      createSharedObject(room, "sampleSO", true);
      ISharedObject so = getSharedObject(room, "sampleSO");

      // Now you could do something with the shared object...

      return true;
  }

}

 如果需要創建 application 作用域 SharedObject ,那麼你需要在appStart 方法中做如同上面代碼所做工作

 

自己創建 ShareObject  問題

其中一個有利因素是你可在SharedObject 增加一個監聽,當客戶連接到SharedObject 時,你可以更新數據或者斷開連接等等。

 客戶端 還是 服務端  初始SharedObject 

在java 服務端創建 SharedObject  會有意料不到的問題(至少對我來說有),這些問題大部分與客戶端,服務端初始化 SharedObject  有關。

當然所有的 SharedObject  都是在red5server 上創建的,但是不同之處是在哪兒初始化。

 

a)服務端初始化 SharedObject  ,SharedObject  是同過java 服務端  調用createSharedObject 創建的,創建後就等待客戶端的連接

 

b)客戶端是初始化SharedObject  是客戶端連接到服務端時候,服務端發現不存在SharedObject 然後自動創建的。

問題會出現在你自定義服務端代碼來創建SharedObject  

例如我想創建 application 作用域名叫 "chat " 的SharedObject  ,並且添加一個監聽,所以我在appStart 加入如下的代碼:

createSharedObject(scope, "chat", false);
ISharedObject so = getSharedObject(scope, "chat");
ISharedObjectListener listener = new MyCustomListener();
so.addSharedObjectListener(listener);

 appStart 方法在服務器啓動時只被調用一次,啓動後服務端創建名叫chat 的 SharedObject 對象 。客戶端可以用application 作用域連接到 chat 對象,至此所有的工作都很正常。

但是當所有的客戶端斷開chat 的連接後,由服務端創建的chat 會被red5服務器銷燬,之後當客戶端再次連接chat 對象,red5 將找不到 chat 對象並自動創建一個 chat 。新的chat對象 是由客戶端初始化創建的,這自動的創建方式,沒有加入監聽,所以自定義事件將不會得到響應。

這樣的問題不會出現的room 作用域中,假設把上面的代碼放到 roomStart 方法中。當最後一個客戶端斷開連接後 room 也會被銷燬,roomStart 方法在 application 生命週期中將多次被調用,例如:當第一客戶端連接一個room .這種情況下問題會出現在最後的客戶端斷開的不是它連接的room.

 

 

自己創建 ShareObject  問題解決辦法

如果有些類似如SharedObjectCreationHandler 或者 SharedObjectFactory 方法就好了,不幸的是沒有。

但是 ISharedObjectSecurity 提供了此類的解決方案

ISharedObjectSecurity 可以在 Application 中被  registerSharedObjectSecurity 註冊,它被用來控制SharedObject的訪問,它有一個名叫isCreationAllowed事件方法,該方法在自動創建ObjectSecurity 前判斷能否被調用方法創建。

代碼如下:

import static org.red5.server.api.ScopeUtils.getScopeService;
...

  public class MySecurityHandler implements ISharedObjectSecurity
  {

  ...

  public boolean isCreationAllowed(IScope scope, String name, boolean persistent)
  {
    if ( "chat".equals(name) )
    {
      // get the SO creation service. Basically the following lines are exactly
      // what MultiThreadedApplicationAdapter does. You can also pass a reference
      // to your Application to this SecurityHandler and use it instead
      ISharedObjectService service = (ISharedObjectService) getScopeService(
            scope,
            ISharedObjectService.class,
            SharedObjectService.class,
            false
      );

      if( service.createSharedObject(scope, name, persistent) == true )
      {
        ISharedObject so = service.getSharedObject(scope, name);
        ISharedObjectListener listener = new MyCustomListener();
        so.addSharedObjectListener(listener);
      }
    }
    return true;
  }

  ...

}

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章