|
#region Using directives
using System;
using System.Collections.Generic;
using System.Text;
#endregion
namespace SharedLibrary
{
public interface ISharedMessage
{
void SendMessage(string message, string sender);
}
}
#region Using directives
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
#endregion
namespace IpcServer
{
public delegate void OnMessageReceivedDelegate(string message, string sender);
public class SharedMessage : MarshalByRefObject, SharedLibrary.ISharedMessage
{
public event OnMessageReceivedDelegate OnMessageReceived;
public SharedMessage()
{
}
public void SendMessage(string message, string sender)
{
if ((OnMessageReceived != null) &&
(OnMessageReceived.GetInvocationList().Length > 0))
OnMessageReceived(message, sender);
}
}
}
#region Using directives
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Ipc;
#endregion
namespace IpcServer
{
partial class frmMain : Form
{
private SharedMessage sm;
private delegate void ShowMessageDelegate(string message, string sender);
private ShowMessageDelegate showMessage;
public frmMain()
{
InitializeComponent();
// need this or we can't use delegates and remoting.
BinaryServerFormatterSinkProvider serverProv = new BinaryServerFormatterSinkProvider();
serverProv.TypeFilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;
BinaryClientFormatterSinkProvider clientProv = new BinaryClientFormatterSinkProvider();
System.Collections.Hashtable properties = new System.Collections.Hashtable();
properties["portName"] = "MessageServer";
IpcChannel ipc = new IpcChannel(properties, clientProv, serverProv);
ChannelServices.RegisterChannel(ipc);
RemotingConfiguration.RegisterWellKnownServiceType(
typeof(SharedMessage), "MessageServer.rem", WellKnownObjectMode.Singleton);
sm = (SharedMessage)Activator.GetObject(typeof(SharedMessage), "ipc://MessageServer/MessageServer.rem");
showMessage = new ShowMessageDelegate(ShowReceivedMessage);
sm.OnMessageReceived +=new OnMessageReceivedDelegate(sm_OnMessageReceived);
}
void sm_OnMessageReceived(string message, string sender)
{
this.Invoke(showMessage, new object[] { message, sender });
}
public void ShowReceivedMessage(string message, string sender)
{
ListViewItem lvi = new ListViewItem();
lvi.Text = message;
lvi.SubItems.Add(sender);
lvMessages.Items.Add(lvi);
}
}
}
#region Using directives
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Ipc;
using SharedLibrary;
#endregion
namespace IpcClient
{
class Program
{
static void Main(string[] args)
{
IpcChannel ipc = new IpcChannel("MessageClient");
ChannelServices.RegisterChannel(ipc);
ISharedMessage sm = (ISharedMessage)Activator.GetObject(typeof(ISharedMessage),
"ipc://MessageServer/MessageServer.rem");
if (sm == null)
{
Console.WriteLine("Failed to communicate with remote server.");
return;
}
Console.WriteLine("Enter message to send to server:");
string message = Console.ReadLine();
Console.WriteLine("Enter your name (sender):");
string sender = Console.ReadLine();
sm.SendMessage(message, sender);
}
}
}
Hi, I am trying to do remoting using the sample above in .net 1.1, however
I get some runtime exception, can you send me some workspace that compiles
and runs on v1.1?
Thanks.
Thanks a lot, this code is reall cool (was trying some others, but yours
was the only one that worked straigt away)
Response to: Hi, I am trying to do remoting using the sample above in .net
1.1, however I get some runtime exception, can you send me some workspace
that compiles and runs on v1.1? Thanks.
Hi, could you post the source code for the GUI example at the bottom?
I tried the example. Everything works fine after starting the app. But when
you wait a few minutes the remoting does still work, but the event
OnMessageReceived of the shared object is NULL!!! It seems that the client
gets another instance of the server object. How can I avoid this?
to Marco: You have to override method InitializeLifetimeService() with
return null in MarshaledByRefObj Class derivative. It makes Share object
useable for server lifetime.
Thanks for this, it works very well! :-)
Just wanted to share my experience with other readers.... I implemented the
server part of this code in a seperate class, not in the main part of the
form. I kept getting serialization errors!!! The solution was to make my
IPC server class (equivalent to frmMain) inherit from MarshalByRefObject.
your example works fine. but i have implemented the server part to a
windows service. Now, i have an build error: ...'Service....' does not
containt a definition for "Invoke".
-> void sm_OnMessageReceived(string message, string sender)
{
this.Invoke(showMessage, new object[] { message, sender });
}
toprack,
Just out of curiosity, why did you put:
(OnMessageReceived.GetInvocationList().Length > 0)
Works beautifully in C#, but if I convert to VB I get an error--Requested
Service Not Found.
If I remove this line in the Server main form constructor (C# included for
reference)
C#: sm.OnMessageReceived += new
OnMessageReceivedDelegate(sm_OnMessageReceived);
VB: AddHandler
sm.OnMessageReceived, AddressOf sm_OnMessageReceived
The error is gone but the event does not get raised.
Do you possibly have a vb.net version of the code?
I expect there is something I lost in the translation.
It would be greatly appreciated.
Thanks for the brilliant example. This is much better than the other
average "Hello World" examples. I like the fact that it goes into the
details of creating an interface and separating the implementation from the
interface (something missing from other examples that said this was a
preferred method of creating IPC). If anything, that's the one part I
missed in this article--that separating the interface allows you to change
the implementation without recompiling both client and server.
Does anyone know how i can modify this code to send messages from Server to
Client ??
Kevin:
Any chance you can Email your Code to me? or May be post the "IPC Remoting "Real World" Example" in Zip file? I'm googling about Event and IPC for quite a while! Your code seems to be the BEST I ever come across! Let me learn bit by bit about your Full Code.
Thanks, great article! This worked for me fine, but when I moved the server
code to a DLL, the line that wires the OnMessageReceivedDelegate is
throwing an ArgumentException: "Error binding to target method" when
invoked by another executable. I've tried using CreateDelegate and still no
luck.
"D:\Samples\SampleRemoting\SampleRemoting\IPCServer\obj\Debug\IPCServer.exe
' does not contain a static 'Main' method suitable for an entry point
iPCServer " plz help me how to fix "