« Return to Thread: SharedObject experience & tips

Re: SharedObject experience & tips

by Kelvin Luck :: Rate this Message:

Reply to Author | View in Thread

Hi Nik,

Thanks for the detailed response :)

I've added some comments in below...

> i don't think that your problem could be solved with server initiated shared
> objects.
> Because for a client and its sync events it doesn't matter how the shared
> object was created on the server.

Cool - that's one less thing for me to investigate then :)

> It seems to me that your problem is related to the client actionscript code
> you use.
> I tried to reproduce your problem, but for me everything was working as
> expected.

Interesting. I will try and get together a simple test case which shows
my problem in more detail. The particular occasion my problem is now
happening on is when I break the connection to the server by unplugging
and replugging my network cable (as opposed to restarting the server). I
manage to maintain the connection while restarting the server...

> The old instances of NetConnection and
> SharedObject have to be replaced.

This is interesting. I am not replacing the NetConnection instance
currently (I am just calling connect() on the existing instance). I will
try removing and recreating the NetConnection instance and see if that
helps... I am refreshing the shared object by calling
SharedObject.getRemote again so I guess that is OK...

> When that was done, all sync events are fired again and the SO data prior to
> the server shutdown is of course lost.

Yes - the loss of SO data is of no concern to me so that's fine :)

> There is only one possibility i know, that a serverside iniciated SO could
> be responsible for sync events not to fire.
> That's the case when instead of using SharedObject.setProperty on the
> clientside, you send data to the server via a normal invoke and the server
> is then responsible for adding the data to the SO via
> ISharedObject.setAttribute.

That isn't the case for me. The SharedObjects are only updated by the
clients so I don't need to worry about that...

>
> In the end: When your are changing values of a SO on the clientside, it
> simply does not matter how the SO is created on the serverside.

Cool.

>
> Puh, hopefully you can get what i mean, my english is ...

...very good! Of course I get what you mean!

Thanks for all of your advice,

Kelvin :)

>
> Nik
>
>
> Kelvin Luck wrote:
>> Hi Tonic,
>>
>> Thanks for this thorough and timely write up!
>>
>> I'm not sure if you've been following my "Reconnected client
>> SharedObject sync events not firing" thread but it seems like this
>> information could be very helpful in solving my issues...
>>
>> Do you think that server initiated shared objects might solve my
>> problems with sync events not firing after re-connection?
>>
>> Thanks,
>>
>> Kelvin :)
>>
>> tonic wrote:
>>> Hello Red5 Community,
>>>
>>> i am kind of new to red5 and spend the last days tyring to figure out
>>> how to use shared objects with red5.
>>> In the following lines i like to summarise my experiences. This should
>>> serve as a hint for others who come accross the same questions and
>>> problems that i did.
>>> Please feel free to correct or supplement the following lines where
>>> neccessary.
>>>
>>> When discussing SharedObjects in the following, i refer to Remote Shared
>>> Objects and not Local Shared Objects of course.
>>> I also focus on non-persistent ones.
>>>
>>> *What are SharedObjects good for?*
>>>
>>> SharedObjects (SOs) are helpful to synchronize data between multiple
>>> clients in real-time and to invoke methods on multiple clients at once.
>>>
>>> A Remote SharedObject is an Object which is shared between multiple
>>> clients, namely all clients of the same scope.
>>>
>>> /So what is a Scope? /
>>> You can think of a scope as a chat room which is defined by the *uri*
>>> that is used to connect the server:
>>> e.g. rtmp://localhost/red5test/lobby
>>> red5test is the application scope
>>> lobby is a room scope, a child scope of red5test
>>> for more information on scopes see:
>>> http://jira.red5.org/confluence/display/docs/Scopes+and+Contexts
>>> <http://faindu.wordpress.com/2007/07/09/what-are-remote-shared-object-rso-for/>
>>>
>>> *How to connect to SOs (clientside)?*
>>>
>>> A Client can connect to a SO using the following Actionscript lines:
>>>
>>> // 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");
>>>
>>> *How does red5 handle SOs?*
>>>
>>> If a client connects to a SO, red5 looks into the specified scope if a
>>> SO named e.g. "chat" already exists.
>>> If it does, red5 uses it, if not, red5 creates a new SO for the Scope
>>> and uses that.
>>> When the last client connected to a SO disconnects from it, the SO will
>>> be destroyed (at least for non-persistent ones).
>>>
>>> *SOs on the serverside*
>>>
>>> */a) Access SOs on the serverside/*
>>> SOs can also be accessed from the serverside, i.e. the server also can
>>> make changes to the SO and broadcast them to all connected clients.
>>>
>>> To check wether a certain SO exists you can use the following lines in
>>> your Java Application:
>>>
>>> //get scope of the current connection first
>>> IScope scope = Red5.getConnectionLocal().getScope();
>>> // get SO
>>> ISharedObject so = getSharedObject(scope, "chat");
>>>
>>> */b) Create SOs on the serverside/*
>>>
>>> You can also create SOs on the serverside with the following lines:
>>>
>>> extracted from Joachim Bauchs tutorial
>>> (http://www.joachim-bauch.de/tutorials/red5/MigrationGuide.txt#sharedobjects):
>>>
>>> To create a new shared object when a room is created, you can override
>>> the method roomStart in your application:
>>>
>>> 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;            
>>>   }
>>>  
>>> }
>>>
>>> If a shared object should be created for connections to the main
>>> application, e.g. rtmp://server/application, the same must be done in
>>> the method appStart.
>>>
>>> ---
>>> <http://www.joachim-bauch.de/tutorials/red5/MigrationGuide.txt#sharedobjects>--
>>>
>>> /*So what is it good for to create SOs by yourself when red5 does it for
>>> you automatically?*/
>>>
>>> One advantage is, that you can attach a Listener to the SO which is
>>> notified when a new client connects to the SO, updates data, disconnects
>>> etc. (See ISharedObjectListener
>>> <http://dl.fancycode.com/red5/api/org/red5/server/api/so/ISharedObjectListener.html>)
>>>
>>> *Problem: clientside initiated vs. serverside initiated SOs*
>>>
>>> Creating SOs in your java application code can leed to some unexpected
>>> problems (It was at least for me).
>>> The problem is related to something i refer to as clientside vs.
>>> serverside initiated SOs.
>>> Of course all SOs wil be created on the red5 server. But there is a
>>> difference who initiated the creation.
>>> a) a serverside initiated SO is a SO that you have created with
>>> createSharedObject in your serverside code. It is then waiting for
>>> clients to connect.
>>> When a client connects to this SO, your custom implementation will be
>>> used.
>>> b) a clientside initiated SO is a "generic" SO that red5 automatically
>>> creates right in the moment when red5 recognizes that the SO a client
>>> connects does not exist.
>>>
>>> The problem arises when you want to create a custom serverside SO for
>>> the main application:
>>> e.g. I want to create an SO named "chat" in the main application scope
>>> and add a listener to it. So i put the following lines in my appStart
>>> method:
>>>
>>> createSharedObject(scope, "chat", false);
>>> ISharedObject so = getSharedObject(scope, "chat");
>>> ISharedObjectListener listener = new MyCustomListener();
>>> so.addSharedObjectListener(listener);
>>>
>>> Now when i start the server, *appStart* is called once the Application
>>> starts.
>>> My custom SO named "chat " will be created (a serverside-initiated SO).
>>> Now when a client connects to the SO named "chat" in the main
>>> application scope, my custom SO will be used by red5.
>>> Everything works fine untill now.
>>> But when all clients disconnect form this SO, my custom, serverside
>>> initiated SO will be destroyed by red5.
>>> After that, when a client connects to the SO named "chat", red5 won't
>>> find it anymore and will automatically create a new "genric" one.
>>> This new one now is clientside initiated, as i did not create it in the
>>> serverside code with createSharedObject.
>>> The difference now is, that no listener is attached to the new generic
>>> SO, and so no events will be fired anymore.
>>>
>>> This problem is not that severe for SOs in a room scope. In this case
>>> you put your creation code inside the *roomStart* method.
>>> As the room is also destroyed when the last connected client
>>> disconnects, the roomStart method will be called multiple times during
>>> the application lifecycle, i.e. everytime the first client connects to a
>>> room. In this case the problem only arises when the last client
>>> disconnects from the SO but not the room.
>>>
>>> /*So what solution is there to this problem?*/
>>>
>>> It would be good to have something like a SharedObjectCreationHandler or
>>> a SharedObjectFactory, but unfortunately there is nothing like that.
>>> But there is a Handler which handles sort of SO creation events: the
>>> ISharedObjectSecurity
>>> <http://dl.fancycode.com/red5/api/org/red5/server/api/so/ISharedObjectSecurity.html>.
>>> This handler can be registered in the Application by
>>> registerSharedObjectSecurity
>>> <http://dl.fancycode.com/red5/api/org/red5/server/adapter/MultiThreadedApplicationAdapter.html#registerSharedObjectSecurity%28org.red5.server.api.so.ISharedObjectSecurity%29>.
>>> Its use is to controll access to shared objects.
>>> It contains an event method named *isCreationAllowed*: Prior to
>>> automatically creating a SO red5 checks if creation is allowed by
>>> calling this method.
>>> Now if you want a custom serverside initiated SO to be created everytime
>>> red5 automatically tries to create a SO, you can put your SO creation
>>> code inside this method and return true.
>>> Red5 then knows creation is allowed and tries to create a SO. To do this
>>> red5f first checks if the SO already exists and !big surprise! it does,
>>> so red5 uses it and does not create one on its own.
>>>
>>> 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;
>>>   }
>>>
>>>   ...
>>>
>>> }
>>>
>>> The method described here, was also discussed in: [Red5] creation
>>> handler to ShareObject
>>> <http://osflash.org/pipermail/red5_osflash.org/2008-February/018579.html>
>>>
>>> *Last but not the least: When is it better to use a SharedObject and
>>> when to use invokes?*
>>>
>>> Here is good mail discussing that topic:
>>> /http://osflash.org/pipermail/red5_osflash.org/2007-August/014406.html/
>>>
>>> That's all,
>>> hopefully it helps somebody.
>>>
>>> Cheers,
>>> Nik
>>>
>>> -----------------
>>>
>>> Further tutorials on SOs:
>>>
>>> What are Remote Shared Objects (RSO) for?
>>> <http://faindu.wordpress.com/2007/07/09/what-are-remote-shared-object-rso-for/>http://www.joachim-bauch.de/tutorials/red5/MigrationGuide.txt#sharedobjects
>>> http://www.joachim-bauch.de/tutorials/red5/HOWTO-Security.txt#shared-objects
>>> Shared Whiteboard application in Red5
>>> <http://sunil-gupta.blogspot.com/2007/04/shared-whiteboard-application-in-red5.html>
>>>
>>>
>>> ------------------------------------------------------------------------
>>> View this message in context: SharedObject experience & tips
>>> <http://www.nabble.com/SharedObject-experience---tips-tp16010760p16010760.html>
>>> Sent from the Red5 - English mailing list archive
>>> <http://www.nabble.com/Red5---English-f16329.html> at Nabble.com.
>>>
>>>
>>> ------------------------------------------------------------------------
>>>
>>> _______________________________________________
>>> Red5 mailing list
>>> Red5@...
>>> http://osflash.org/mailman/listinfo/red5_osflash.org
>> _______________________________________________
>> Red5 mailing list
>> Red5@...
>> http://osflash.org/mailman/listinfo/red5_osflash.org
>>
>>
>

_______________________________________________
Red5 mailing list
Red5@...
http://osflash.org/mailman/listinfo/red5_osflash.org

 « Return to Thread: SharedObject experience & tips