[Mono-list] Bi-directional remoting
Urs Muff
umuff@quark.com
Fri, 21 Feb 2003 11:26:22 -0700
This message is in MIME format. Since your mail reader does not understand
this format, some or all of this message may not be legible.
------_=_NextPart_001_01C2D9D6.BC8819A0
Content-Type: text/plain
How would you create such a bi-directional channel? All the samples I used
so far are only server-client, but not the other way around.
I have a delegate that I want to implement on the client side. The class
implementing the callback sits on the client (of course).
I even use the common abstract pattern described by a Microsoft KB article,
but still no luck.
Debug output:
ASP.Net Server starting
Server.Do start
An unhandled exception of type 'System.Runtime.Remoting.RemotingException'
occurred in mscorlib.dll
Additional information: This remoting proxy has no channel sink which means
either the server has no registered server channels that are listening, or
this application has no suitable client channel to talk to the server.
Here is the sample code:
CommonLib: [both server and client have access]
-----------------------------------------------
using System;
using System.Runtime.Remoting;
public delegate void BaseEventHandler(object sender,RemoteEventArgs e);
[Serializable]
public class RemoteEventArgs : EventArgs
{
public static new RemoteEventArgs Empty = new RemoteEventArgs();
}
public abstract class RemoteCallback : MarshalByRefObject
{
[System.Runtime.Remoting.Messaging.OneWay]
public void Callback(object sender,RemoteEventArgs e)
{
CallbackImpl(sender,e);
}
protected abstract void CallbackImpl(object sender,RemoteEventArgs
e);
}
public interface IServer
{
event BaseEventHandler Evt;
void Do();
}
ASP.Net Server:
--------------------------------------------
class S : MarshalByRefObject, IServer
{
public event BaseEventHandler Evt;
public void Do()
{
System.Diagnostics.Debug.WriteLine("Server.Do start");
if (Evt != null) Evt(this,RemoteEventArgs.Empty);
System.Diagnostics.Debug.WriteLine("Server.Do end");
}
}
public class Service1 : System.Web.Services.WebService
{
... // standard web service stuff (autogenerated)
static bool Init = false;
[WebMethod]
public void StartUp()
{
if (!Init)
{
RemotingConfiguration.Configure("/Server.config");
Init = true;
}
System.Diagnostics.Debug.WriteLine("ASP.Net Server
starting");
}
}
<configuration>
<system.runtime.remoting>
<application>
<service>
<wellknown
mode="Singleton"
type="S, Server"
objectUri="S"
/>
</service>
<channels>
<channel ref="tcp" port="8085">
<serverProviders>
<formatter ref="binary"/>
</serverProviders>
</channel>
</channels>
</application>
</system.runtime.remoting>
</configuration>
Client:
--------------------------------------------
using System;
using System.Runtime.Remoting;
public class Test
{
static void Main()
{
RemotingConfiguration.Configure("../../Client.config");
new Client.localhost.Service1().StartUp();
IServer s =
Activator.GetObject(typeof(IServer),"tcp://localhost:8085/S") as IServer;
s.Evt += new BaseEventHandler(
new ClientChangedCallback().Callback);
s.Do();
System.Diagnostics.Debug.WriteLine("I never get here");
}
}
public class ClientChangedCallback : RemoteCallback
{
protected override void CallbackImpl(object sender,RemoteEventArgs
e)
{
System.Diagnostics.Debug.WriteLine("And of course I never
get here");
}
}
<configuration>
<system.runtime.remoting>
<application>
<channels>
<channel ref="tcp">
<clientProviders>
<formatter ref="binary"/>
</clientProviders>
</channel>
</channels>
</application>
</system.runtime.remoting>
</configuration>
------_=_NextPart_001_01C2D9D6.BC8819A0
Content-Type: text/html
Content-Transfer-Encoding: quoted-printable
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<META HTTP-EQUIV=3D"Content-Type" CONTENT=3D"text/html; =
charset=3DUS-ASCII">
<META NAME=3D"Generator" CONTENT=3D"MS Exchange Server version =
5.5.2653.12">
<TITLE>Bi-directional remoting</TITLE>
</HEAD>
<BODY>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" FACE=3D"Courier">How would you =
create such a bi-directional channel? All the samples I used so =
far are only server-client, but not the other way around.</FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" FACE=3D"Courier">I have a =
delegate that I want to implement on the client side. The class =
implementing the callback sits on the client (of course).</FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" FACE=3D"Courier">I even use the =
common abstract pattern described by a</FONT> <FONT COLOR=3D"#000000" =
FACE=3D"Courier">Microsoft</FONT><FONT COLOR=3D"#000000" =
FACE=3D"Courier"> KB article, but still no luck.</FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" FACE=3D"Courier">Debug =
output:</FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" FACE=3D"Courier">ASP.Net Server =
starting</FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" FACE=3D"Courier">Server.Do =
start</FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" FACE=3D"Courier">An unhandled =
exception of type 'System.Runtime.Remoting.RemotingException' occurred =
in mscorlib.dll</FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" FACE=3D"Courier">Additional =
information: This remoting proxy has no channel sink which means either =
the server has no registered server channels that are listening, or =
this application has no suitable client channel to talk to the =
server.</FONT></P>
<BR>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" FACE=3D"Courier">Here is the =
sample code:</FONT></P>
<BR>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" FACE=3D"Courier">CommonLib: =
[both server and client have access]</FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" =
FACE=3D"Courier">-----------------------------------------------</FONT><=
/P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" FACE=3D"Courier">using =
System;</FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" FACE=3D"Courier">using =
System.Runtime.Remoting;</FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" FACE=3D"Courier">public =
delegate void BaseEventHandler(object sender,RemoteEventArgs =
e);</FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" =
FACE=3D"Courier">[Serializable]</FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" FACE=3D"Courier">public class =
RemoteEventArgs : EventArgs</FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" FACE=3D"Courier">{</FONT></P>
<P ALIGN=3DLEFT> <FONT =
COLOR=3D"#000000" FACE=3D"Courier">public static new RemoteEventArgs =
Empty =3D new RemoteEventArgs();</FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" FACE=3D"Courier">}</FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" FACE=3D"Courier">public =
abstract class RemoteCallback : MarshalByRefObject</FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" FACE=3D"Courier">{</FONT></P>
<P ALIGN=3DLEFT> <FONT =
COLOR=3D"#000000" =
FACE=3D"Courier">[System.Runtime.Remoting.Messaging.OneWay]</FONT></P>
<P ALIGN=3DLEFT> <FONT =
COLOR=3D"#000000" FACE=3D"Courier">public void Callback(object =
sender,RemoteEventArgs e)</FONT></P>
<P ALIGN=3DLEFT> <FONT =
COLOR=3D"#000000" FACE=3D"Courier">{</FONT></P>
<P ALIGN=3DLEFT> =
<FONT COLOR=3D"#000000" =
FACE=3D"Courier">CallbackImpl(sender,e);</FONT></P>
<P ALIGN=3DLEFT> <FONT =
COLOR=3D"#000000" FACE=3D"Courier">}</FONT></P>
<P ALIGN=3DLEFT> <FONT =
COLOR=3D"#000000" FACE=3D"Courier">protected abstract void =
CallbackImpl(object sender,RemoteEventArgs e);</FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" FACE=3D"Courier">}</FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" FACE=3D"Courier">public =
interface IServer</FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" FACE=3D"Courier">{</FONT></P>
<P ALIGN=3DLEFT> <FONT =
COLOR=3D"#000000" FACE=3D"Courier">event BaseEventHandler =
Evt;</FONT></P>
<P ALIGN=3DLEFT> <FONT =
COLOR=3D"#000000" FACE=3D"Courier">void Do();</FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" FACE=3D"Courier">}</FONT></P>
<BR>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" FACE=3D"Courier">ASP.Net =
Server:</FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" =
FACE=3D"Courier">--------------------------------------------</FONT></P>=
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" FACE=3D"Courier">class S : =
MarshalByRefObject, IServer</FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" FACE=3D"Courier">{</FONT></P>
<P ALIGN=3DLEFT> <FONT =
COLOR=3D"#000000" FACE=3D"Courier">public event BaseEventHandler =
Evt;</FONT></P>
<P ALIGN=3DLEFT> <FONT =
COLOR=3D"#000000" FACE=3D"Courier">public void Do()</FONT></P>
<P ALIGN=3DLEFT> <FONT =
COLOR=3D"#000000" FACE=3D"Courier">{</FONT></P>
<P ALIGN=3DLEFT> =
<FONT COLOR=3D"#000000" =
FACE=3D"Courier">System.Diagnostics.Debug.WriteLine("Server.Do =
start");</FONT></P>
<P ALIGN=3DLEFT> =
<FONT COLOR=3D"#000000" =
FACE=3D"Courier">if (Evt !=3D null) =
Evt(this,RemoteEventArgs.Empty);</FONT></P>
<P ALIGN=3DLEFT> =
<FONT COLOR=3D"#000000" =
FACE=3D"Courier">System.Diagnostics.Debug.WriteLine("Server.Do =
end");</FONT></P>
<P ALIGN=3DLEFT> <FONT =
COLOR=3D"#000000" FACE=3D"Courier">}</FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" FACE=3D"Courier">}</FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" FACE=3D"Courier">public class =
Service1 : System.Web.Services.WebService</FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" FACE=3D"Courier">{</FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" =
FACE=3D"Courier"> ... // standard =
web service stuff (autogenerated)</FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" FACE=3D"Courier"> =
static bool Init =3D false;</FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" =
FACE=3D"Courier"> =
[WebMethod]</FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" =
FACE=3D"Courier"> public void =
StartUp()</FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" =
FACE=3D"Courier"> {</FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" =
FACE=3D"Courier"> =
if (!Init)</FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" =
FACE=3D"Courier"> =
{</FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" =
FACE=3D"Courier"> =
=
=
RemotingConfiguration.Configure("</FONT><FONT COLOR=3D"#000000" =
FACE=3D"Courier">/</FONT><FONT COLOR=3D"#000000" =
FACE=3D"Courier">Server.config");</FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" =
FACE=3D"Courier"> =
=
Init =3D true;</FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" =
FACE=3D"Courier"> =
}</FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" =
FACE=3D"Courier"> =
=
System.Diagnostics.Debug.WriteLine("ASP.Net Server =
starting");</FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" =
FACE=3D"Courier"> }</FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" FACE=3D"Courier">}</FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" =
FACE=3D"Courier"><configuration></FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" FACE=3D"Courier"> =
<system.runtime.remoting></FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" =
FACE=3D"Courier"> <application></FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" =
FACE=3D"Courier"> =
<service></FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" =
FACE=3D"Courier"> =
<wellknown </FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" =
FACE=3D"Courier"> &=
nbsp; mode=3D"Singleton" </FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" =
FACE=3D"Courier"> &=
nbsp; type=3D"S, Server" </FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" =
FACE=3D"Courier"> &=
nbsp; objectUri=3D"S"</FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" =
FACE=3D"Courier"> =
/></FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" =
FACE=3D"Courier"> =
</service></FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" =
FACE=3D"Courier"> =
<channels></FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" =
FACE=3D"Courier"> <channel =
ref=3D"tcp" port=3D"8085"></FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" =
FACE=3D"Courier"> =
<serverProviders></FONT></P>
<P ALIGN=3DLEFT> <FONT =
COLOR=3D"#000000" FACE=3D"Courier"> =
<formatter =
ref=3D"binary"/></FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" =
FACE=3D"Courier"> =
</serverProviders></FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" =
FACE=3D"Courier"> =
</channel></FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" =
FACE=3D"Courier"> =
</channels></FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" =
FACE=3D"Courier"> </application></FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" FACE=3D"Courier"> =
</system.runtime.remoting></FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" =
FACE=3D"Courier"></configuration></FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" =
FACE=3D"Courier">Client:</FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" =
FACE=3D"Courier">--------------------------------------------</FONT></P>=
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" FACE=3D"Courier">using =
System;</FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" FACE=3D"Courier">using =
System.Runtime.Remoting;</FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" FACE=3D"Courier">public class =
Test</FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" FACE=3D"Courier">{</FONT></P>
<P ALIGN=3DLEFT> <FONT =
COLOR=3D"#000000" FACE=3D"Courier">static void Main()</FONT></P>
<P ALIGN=3DLEFT> <FONT =
COLOR=3D"#000000" FACE=3D"Courier">{</FONT></P>
<P ALIGN=3DLEFT> =
<FONT COLOR=3D"#000000" =
FACE=3D"Courier">RemotingConfiguration.Configure("../../Client.conf=
ig");</FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" =
FACE=3D"Courier"> =
</FONT></P>
<P ALIGN=3DLEFT> =
<FONT COLOR=3D"#000000" =
FACE=3D"Courier">new Client.localhost.Service1().StartUp();</FONT></P>
<P ALIGN=3DLEFT> =
<FONT COLOR=3D"#000000" =
FACE=3D"Courier">IServer s =3D =
Activator.GetObject(typeof(IServer),"tcp://localhost:8085/S") =
as IServer;</FONT></P>
<P ALIGN=3DLEFT> =
<FONT COLOR=3D"#000000" =
FACE=3D"Courier">s.Evt +=3D new BaseEventHandler(</FONT></P>
<P ALIGN=3DLEFT> =
=
<FONT COLOR=3D"#000000" =
FACE=3D"Courier">new ClientChangedCallback().Callback);</FONT></P>
<P ALIGN=3DLEFT> =
<FONT COLOR=3D"#000000" =
FACE=3D"Courier">s.Do();</FONT></P>
<P ALIGN=3DLEFT> =
<FONT COLOR=3D"#000000" =
FACE=3D"Courier">System.Diagnostics.Debug.WriteLine("I never get =
here");</FONT></P>
<P ALIGN=3DLEFT> <FONT =
COLOR=3D"#000000" FACE=3D"Courier">}</FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" FACE=3D"Courier">}</FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" FACE=3D"Courier">public class =
ClientChangedCallback : RemoteCallback</FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" FACE=3D"Courier">{</FONT></P>
<P ALIGN=3DLEFT> <FONT =
COLOR=3D"#000000" FACE=3D"Courier">protected override void =
CallbackImpl(object sender,RemoteEventArgs e)</FONT></P>
<P ALIGN=3DLEFT> <FONT =
COLOR=3D"#000000" FACE=3D"Courier">{</FONT></P>
<P ALIGN=3DLEFT> =
<FONT COLOR=3D"#000000" =
FACE=3D"Courier">System.Diagnostics.Debug.WriteLine("And of course =
I never get here");</FONT></P>
<P ALIGN=3DLEFT> <FONT =
COLOR=3D"#000000" FACE=3D"Courier">}</FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" FACE=3D"Courier">}</FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" =
FACE=3D"Courier"><configuration></FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" FACE=3D"Courier"> =
<system.runtime.remoting></FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" =
FACE=3D"Courier"> =
<application></FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" =
FACE=3D"Courier"> =
<channels></FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" =
FACE=3D"Courier"> &=
nbsp; <channel ref=3D"tcp"></FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" =
FACE=3D"Courier"> &=
nbsp; <clientProviders></FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" =
FACE=3D"Courier"> &=
nbsp; <formatter =
ref=3D"binary"/></FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" =
FACE=3D"Courier"> &=
nbsp; </clientProviders></FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" =
FACE=3D"Courier"> &=
nbsp; </channel></FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" =
FACE=3D"Courier"> =
</channels></FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" =
FACE=3D"Courier"> =
</application></FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" FACE=3D"Courier"> =
</system.runtime.remoting></FONT></P>
<P ALIGN=3DLEFT><FONT COLOR=3D"#000000" =
FACE=3D"Courier"></configuration></FONT></P>
</BODY>
</HTML>
------_=_NextPart_001_01C2D9D6.BC8819A0--