Introduction
.NET Remote
objects can be hosted in the .NET Windows EXE server, the Internet
Information Server (IIS) and the .NET component services.
Using object references to communicate between server objects and clients is
the heart of remote. The remote objects are
reusable and lets you design a business logic object model according to the
needs of the application.
The real
strength of the remote system is its ability to transport messages between
remote objects in different application domains or processes using different
transportation protocols, serialization formats, object lifetime schemes.
The server object that
has the ability to handle the callback is very important for some type of
service. For example, when user logon the Auction server to bid an item, the
user need to know the current price of the item. This requires the Auction
Server to have the callback function to send the price information to all
the users they are bid on the item.
In this article we only
discuss how to use event handler to register the client's callback
function (My next article “Remote Object Part 2” will discuss the client sink
its instance to the server). The Server Object declare three events that
can be used by the client to register the event handler in their host or
register their callback function with which client can be called when the
event raise. The clients use server's event handler to register their callback
function is very easy.
SrvObj.SrvMessaging += new ServerEventHandler(CltObj.ServerMsgHandler);
This code add
event handler CltObj.ServerMsgHandler to the event SrvMessaging on SrvObj.
The delegate is derived
from System.MupticasetDelegate, which has a linked list that can hold any
number of the event handler function. So, one event can have multiple event
handlers. This means one event on the server object can handle all the callback
function of the clients that is registered on that event.
The disadvantage of
using event handler to register callback is not flexible for clients and the
Server side can’t control over the clients to register callback function. If
server wants to add more event handlers for different purpose, the client
program has to change its code to use these new event handlers.
Server Object:
namespace WremoteServer
{
public delegate void ServerEventHandler (object sender, RemoteEventArgs e);
public class RemoteServer : MarshalByRefObject
{
public static event ServerEventHandler InvokeHostForm;
public event ServerEventHandler SrvMessaging;
public event ServerEventHandler SrvMessaging2;
public void RemoteServerMethod(string str, out string strOut)
{
string tmp=string.Format("RemoteServerMethod is called: {0}",str);
RemoteEventArgs e = new RemoteEventArgs(tmp);
if(InvokeHostForm != null)
InvokeHostForm(this, e);
strOut = str + " Returned from Server!";
}
public void SendMsgToClient(string str)
{
RemoteEventArgs e = new RemoteEventArgs(str);
if (SrvMessaging != null)
SrvMessaging(this, e);
}
public void SendMsgToClient2(string str)
{
RemoteEventArgs e = new RemoteEventArgs(str);
if (SrvMessaging2 != null)
SrvMessaging2(this, e);
}
}
}
Client Object:
namespace WremoteClient
{
public delegate void CFormEventHandler(object sender, RemoteEventArgs e);
public class RemotingClient : MarshalByRefObject
{
public event CFormEventHandler InvokeFormMethod;
[OneWay]
public void ServerMsgHandler(object sender, RemoteEventArgs e)
{
if(InvokeFormMethod != null)
InvokeFormMethod(this, e);
}
}
}
Client host:
private void ConnSrv_Click(object sender, System.EventArgs e)
{
try
{
if (registedChan != null)
{
ChannelServices.UnregisterChannel(registedChan);
registedChan = null;
unRegistAll();
}
HttpChannel chan = new HttpChannel(Int32.Parse(port.Text));
ChannelServices.RegisterChannel(chan);
registedChan = chan;
SrvObj = (RemoteServer)Activator.GetObject(
typeof(WRemoteServer.RemoteServer),
"http://localhost:8085/RemoteObj");
if (SrvObj == null)
lb.Items.Add("Can't connect to server");
else
{
string strServer;
SrvObj.RemoteServerMethod(tb.Text + " from the client",
out strServer);
lb.Items.Add(strServer);
}
}
catch(Exception e2)
{
lb.Items.Add(e2.Message);
}
}
private void ForMsg1_Click(object sender, System.EventArgs e)
{
if(callbackFlg == false && registedChan != null)
{
RemotingConfiguration.RegisterWellKnownServiceType(
Type.GetType("WRemoteClient.RemotingClient, RemotingClient"),
"ClientObj",
WellKnownObjectMode.Singleton);
string url=String.Format("http://localhost:{0}/ClientObj", port.Text);
CltObj = (RemotingClient)Activator.GetObject(
typeof(WRemoteClient.RemotingClient),
url);
SrvObj.SrvMessaging += new ServerEventHandler(CltObj.ServerMsgHandler);
CltObj.InvokeFormMethod += new CFormEventHandler(OnMsgHandler);
string strServer;
SrvObj.RemoteServerMethod("Callback is registed!", out strServer);
callbackFlg = true;
}
}
Steps to
run the sample:
- Compile
the Remote object by running makefile.bat at RemoteObj directory.
- Compile the WremoteClient
and the WremoteServer. You may need to change the references to these DLL.
- Copy
all the DLL files in RemoteObj directory to the WremoteClient\bin\Debug and
WRemoteServer\bin\Debug directory.
- Run
WRemoteServer.exe
- Run
WRemoteClient.exe, then Click Connect Server, after this, you can send message
to server and get the return message.
- Click
register callback to select which message do you want to registered, after
this, the client is waiting for the server message on the open channel.
Note:
When you want to start more than one client on the same
machine, You should select different port number for the channel that is
reserved for the callback.
This demo
is updated with .Net framework 1.0 Version 1.0.3705. The Beta2 user may
need to replace the control with Beta2 to make it work.
If you have any comments,
I would love to hear about it. You can reach me at
Jibin Pan.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.