Remoting Singleton Issue

  • Thread starter Palvinder Singh
  • Start date
P

Palvinder Singh

Hello google group peeps,

I am new to remoting, but have a grasp of it.

I am trying to create a server/client application, which will be
deployed over an intranet. I have upwards of five clients that connect
to a main server. The client application sets the state of several
switchs (on/off by means of clicking a button). When a switch is
turned on/off, its state is updated on the server, which will then
raise an event to update the other clients switchs to match each other.
i.e. if client A switches switch 3 on, client B, C, D etc... should
show that switch as on. Also I want to be able to check the status of
any switch, by means of checking its value stored on the server at any
given point.

The issue arises, as i think the best concept to use is server
activated, singleton and making it remotable by deriving from
MarshalByRefObject. From my research i found that Singleton is an
object that is instantiated and used by all connecting clients.

I have created a test application, which sets and gets a single value
(default value set to 0) that is stored on the server. When i set that
value to 10 on Client A and get the same value in Client B, Client B
comes back with 0. Client B should, in my thinking, come back with a
value of 10?

Am i mistaken in the way Singleton works and if so what should i be
using instead to maintain state of the switches on the server. Any
appropriate tutorials links would be great. I can also post source code
on request.

Any help appreciated

Regards


Palvinder
 
D

Dave Sexton

Hi Palvinder,
I am new to remoting, but have a grasp of it.

I am trying to create a server/client application, which will be
deployed over an intranet. I have upwards of five clients that connect
to a main server. The client application sets the state of several
switchs (on/off by means of clicking a button). When a switch is
turned on/off, its state is updated on the server, which will then
raise an event to update the other clients switchs to match each other.
i.e. if client A switches switch 3 on, client B, C, D etc... should
show that switch as on. Also I want to be able to check the status of
any switch, by means of checking its value stored on the server at any
given point.

The issue arises, as i think the best concept to use is server
activated, singleton and making it remotable by deriving from
MarshalByRefObject. From my research i found that Singleton is an
object that is instantiated and used by all connecting clients.

That is correct.
I have created a test application, which sets and gets a single value
(default value set to 0) that is stored on the server. When i set that
value to 10 on Client A and get the same value in Client B, Client B
comes back with 0. Client B should, in my thinking, come back with a
value of 10?

If you're using a configuration file for your settings, be sure to use the
correct xml on the server [1] and client [2].

If you're programmatically configuring your remoting object then be sure to
use the correct registration method on the server [3] and client [4].
Am i mistaken in the way Singleton works and if so what should i be
using instead to maintain state of the switches on the server. Any
appropriate tutorials links would be great. I can also post source code
on request.

Your understanding of Singleton is accurate, however there is one
complication with remoting: leasing [5].

If registration is accurate, then make sure that you override the default
leasing behavior:

public class MyClass : MarshalByRefObject
{
public override Object InitializeLifetimeService()
{
return null;
}
}

Also, read the other issues presented in [5].

--
Dave Sexton

[1] .NET Framework General Reference, <wellknown> Element (Service Instance)
http://msdn.microsoft.com/library/d...genref/html/gnconWellknownServiceInstance.asp

[2] .NET Framework General Reference, <wellknown> Element (Client Instance)
http://msdn.microsoft.com/library/d...pgenref/html/gnconWellknownClientInstance.asp

[3] RemotingConfiguration.RegisterWellKnownServiceType Method
http://msdn2.microsoft.com/en-us/li...nfiguration.registerwellknownservicetype.aspx

[4] RemotingConfiguration.RegisterWellKnownClientType Method
http://msdn2.microsoft.com/en-us/li...onfiguration.registerwellknownclienttype.aspx

[5] .NET Development (General) Technical Articles, .NET Remoting
Architectural Assessment
§ Server-ActivatedObjects, Singleton
http://msdn2.microsoft.com/en-us/library/ms973841.aspx
 
D

Dave Sexton

Hi Palvinder,
I am new to remoting, but have a grasp of it.

I am trying to create a server/client application, which will be
deployed over an intranet. I have upwards of five clients that connect
to a main server. The client application sets the state of several
switchs (on/off by means of clicking a button). When a switch is
turned on/off, its state is updated on the server, which will then
raise an event to update the other clients switchs to match each other.
i.e. if client A switches switch 3 on, client B, C, D etc... should
show that switch as on. Also I want to be able to check the status of
any switch, by means of checking its value stored on the server at any
given point.

The issue arises, as i think the best concept to use is server
activated, singleton and making it remotable by deriving from
MarshalByRefObject. From my research i found that Singleton is an
object that is instantiated and used by all connecting clients.

That is correct.
I have created a test application, which sets and gets a single value
(default value set to 0) that is stored on the server. When i set that
value to 10 on Client A and get the same value in Client B, Client B
comes back with 0. Client B should, in my thinking, come back with a
value of 10?

If you're using a configuration file for your settings, be sure to use the
correct xml on the server [1] and client [2].

If you're programmatically configuring your remoting object then be sure to
use the correct registration method on the server [3] and client [4].
Am i mistaken in the way Singleton works and if so what should i be
using instead to maintain state of the switches on the server. Any
appropriate tutorials links would be great. I can also post source code
on request.

Your understanding of Singleton is accurate, however there is one
complication with remoting: leasing [5].

If registration is accurate, then make sure that you override the default
leasing behavior:

public class MyClass : MarshalByRefObject
{
public override Object InitializeLifetimeService()
{
return null;
}
}

Also, read the other issues presented in [5].

--
Dave Sexton

[1] .NET Framework General Reference, <wellknown> Element (Service Instance)
http://msdn.microsoft.com/library/d...genref/html/gnconWellknownServiceInstance.asp

[2] .NET Framework General Reference, <wellknown> Element (Client Instance)
http://msdn.microsoft.com/library/d...pgenref/html/gnconWellknownClientInstance.asp

[3] RemotingConfiguration.RegisterWellKnownServiceType Method
http://msdn2.microsoft.com/en-us/li...nfiguration.registerwellknownservicetype.aspx

[4] RemotingConfiguration.RegisterWellKnownClientType Method
http://msdn2.microsoft.com/en-us/li...onfiguration.registerwellknownclienttype.aspx

[5] .NET Development (General) Technical Articles, .NET Remoting
Architectural Assessment
§ Server-ActivatedObjects, Singleton
http://msdn2.microsoft.com/en-us/library/ms973841.aspx
 
P

Palvinder Singh

Thanks for your reply,

i have posted my code as i am positive i am missing something along the
way. How do i know if my config files are correct and that the
application is getting there values?

a)i use a property and a method to retrieve the values, also commented
out 'InitializeLifetimeService' as it had no effect;

using System;
/// <summary>
/// Remotable class
/// </summary>
public class RemoteObject : MarshalByRefObject
{
private int savedNumber;
public int MyNumber
{
get{ return savedNumber; }
set{ savedNumber = value; }
}

public RemoteObject() {}

//public override Object InitializeLifetimeService()
//{
// Allow this object to live "forever"
//return null;
//}

public int GetNumber()
{
return savedNumber;
}
}


b) i use a config file to set the channels etc, is this okay?

using System;
using System.Runtime.Remoting;
/// <summary>
/// Server, component host
/// </summary>
class HostObject
{
[STAThread]
static void Main(string[] args)
{
//register remotable classes
RemotingConfiguration.Configure(@"ComponentHost.exe.config");

Console.WriteLine("press any key to quit...");
Console.ReadLine();
}
}

and its config file;

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.runtime.remoting>
<application>
<!--Define remotable object-->
<service>
<wellknown
mode = "Singleton"
type = "RemotableObjects.RemoteObject,
RemotableObjects"
objectUri = "RemoteObject">
</wellknown>
</service>

<!--Define the protocol used for network acess (tcp or
http)-->
<channels>
<channel ref = "tcp" port = "9090" />
</channels>
</application>
</system.runtime.remoting>
</configuration>


c) Where u see '.....' i have remove commonly seen code in forms. Also
where i define 'proxy', i have added a reference to my remotableobject
dll , is this correct?

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Runtime.Remoting;


namespace Client
{
public class ClientObject:System.Windows.Forms.Form
{
RemoteObject proxy = new RemoteObject();

private System.Windows.Forms.Button button1;
private System.Windows.Forms.TextBox textBox1;
private System.Windows.Forms.Button button2;


private System.ComponentModel.Container components = null;

public ClientObject()
{.....}

protected override void Dispose( bool disposing )
{.....}

//#region Windows Form Designer generated code.....

[STAThread]
static void Main()
{
Application.Run(new ClientObject());

RemotingConfiguration.Configure(@"ClientApplication.exe.config");

}

private void button1_Click(object sender, System.EventArgs e)
{
int clientNumber = proxy.GetNumber();
textBox1.Text = clientNumber.ToString();
}

private void button2_Click(object sender, System.EventArgs e)
{
proxy.MyNumber = int.Parse(textBox1.Text);
textBox1.Text = "set complete";
}
}
}

and finally the config for the client

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.runtime.remoting>
<application>
<!--Define the object this application will use
remotely.-->
<client>
<wellknown
type = "RemotableObjects.RemoteObject,
RemotableObjects"
url = "tcp://sony:9090/RemoteObject">
</wellknown>
</client>

<!--Define the protocol used for network acess (tcp or
http)-->
<channels>
<channel ref = "tcp" port = "0" />
</channels>
</application>
</system.runtime.remoting>
</configuration>


Regards

Palvinder
 
P

Palvinder Singh

One more thing i have noticed is that if i open two clients up on their
own, they seem to still work, i.e. they dont error out as i would
expect it would if no host was present.

Also when just the two clients are opened without the host you can
still set and get values, but again when Client A is 'set' to 33, and
you 'get' the value from Client B the default value 0 is returned. So
has this got anything to do with the fact that i have added a
referrence to the remoteobject.dll into my client application?

Regards

PS
 
D

Dave Sexton

Hi Palvinder,

Application.Run is a blocking call. You'll notice that if you add a
breakpoint to the line in which you perform remoting configuration on the
client that it doesn't get executed until after you exit the application, by
closing the ClientObject Form, for instance.

Try the following instead:

[STAThread]
static void Main()
{
RemotingConfiguration.Configure(@"ClientApplication.exe.config");
Application.Run(new ClientObject());
}
RemoteObject proxy = new RemoteObject();

In your example this code is just creating an instance of the object on the
client, which is why you keep getting 0 and don't need an instance of the
server running. Adding the configuration as above should fix the problem by
telling the remoting framework to connect to the configured URI for the
server-activated object before code with the "new" keyword is used to try to
create an instance.

Everything else seems fine :)

BTW, you might want to post Remoting questions to the
microsoft.public.dotnet.framework.remoting newsgroup in the future.

--
Dave Sexton

Palvinder Singh said:
Thanks for your reply,

i have posted my code as i am positive i am missing something along the
way. How do i know if my config files are correct and that the
application is getting there values?

a)i use a property and a method to retrieve the values, also commented
out 'InitializeLifetimeService' as it had no effect;

using System;
/// <summary>
/// Remotable class
/// </summary>
public class RemoteObject : MarshalByRefObject
{
private int savedNumber;
public int MyNumber
{
get{ return savedNumber; }
set{ savedNumber = value; }
}

public RemoteObject() {}

//public override Object InitializeLifetimeService()
//{
// Allow this object to live "forever"
//return null;
//}

public int GetNumber()
{
return savedNumber;
}
}


b) i use a config file to set the channels etc, is this okay?

using System;
using System.Runtime.Remoting;
/// <summary>
/// Server, component host
/// </summary>
class HostObject
{
[STAThread]
static void Main(string[] args)
{
//register remotable classes
RemotingConfiguration.Configure(@"ComponentHost.exe.config");

Console.WriteLine("press any key to quit...");
Console.ReadLine();
}
}

and its config file;

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.runtime.remoting>
<application>
<!--Define remotable object-->
<service>
<wellknown
mode = "Singleton"
type = "RemotableObjects.RemoteObject,
RemotableObjects"
objectUri = "RemoteObject">
</wellknown>
</service>

<!--Define the protocol used for network acess (tcp or
http)-->
<channels>
<channel ref = "tcp" port = "9090" />
</channels>
</application>
</system.runtime.remoting>
</configuration>


c) Where u see '.....' i have remove commonly seen code in forms. Also
where i define 'proxy', i have added a reference to my remotableobject
dll , is this correct?

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Runtime.Remoting;


namespace Client
{
public class ClientObject:System.Windows.Forms.Form
{
RemoteObject proxy = new RemoteObject();

private System.Windows.Forms.Button button1;
private System.Windows.Forms.TextBox textBox1;
private System.Windows.Forms.Button button2;


private System.ComponentModel.Container components = null;

public ClientObject()
{.....}

protected override void Dispose( bool disposing )
{.....}

//#region Windows Form Designer generated code.....

[STAThread]
static void Main()
{
Application.Run(new ClientObject());

RemotingConfiguration.Configure(@"ClientApplication.exe.config");

}

private void button1_Click(object sender, System.EventArgs e)
{
int clientNumber = proxy.GetNumber();
textBox1.Text = clientNumber.ToString();
}

private void button2_Click(object sender, System.EventArgs e)
{
proxy.MyNumber = int.Parse(textBox1.Text);
textBox1.Text = "set complete";
}
}
}

and finally the config for the client

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.runtime.remoting>
<application>
<!--Define the object this application will use
remotely.-->
<client>
<wellknown
type = "RemotableObjects.RemoteObject,
RemotableObjects"
url = "tcp://sony:9090/RemoteObject">
</wellknown>
</client>

<!--Define the protocol used for network acess (tcp or
http)-->
<channels>
<channel ref = "tcp" port = "0" />
</channels>
</application>
</system.runtime.remoting>
</configuration>


Regards

Palvinder
 
P

Palvinder Singh

Thanks Dave for all your help, its working now.

Regards


Palvinder Singh
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top