We all know that we can achieve inter-process communication using COM, but what are the other options?
Without relying on an antique technology, we can assume that the modern way of exchanging data between applications based on the .Net framework is to rely on WCF.
For those who are not familiar with it, here is how MSDN introduces WCF on its webpage:
Windows Communication Foundation (WCF) is a framework for building service-oriented applications. Using WCF, you can send data as asynchronous messages from one service endpoint to another. A service endpoint can be part of a continuously available service hosted by IIS, or it can be a service hosted in an application. An endpoint can be a client of a service that requests data from a service endpoint.
I’ve been already exposing extensively on that same blog how to use WCF to create web services in my series Creating a cloud based viewer – Part I to X. I won’t go back through the basics today.
Out goal here is to exchange data between two processes running on the same machine. There will be one server process and one or several client processes that connect to it. The server will be able to eventually dispatch the data sent by one client to the others.
Among other things, WCF is using bindings. Bindings are used to specify the transport, encoding, and protocol details required for clients and services to communicate with each other. The first thing we have to determine when using WCF is which kind of binding we are going to use and this is mostly defined by our scenario.
The following diagram should help you to determine which binding you need considering your situation (just click on it as it appears too tiny on that page):
In our case today, we have two WCF applications running on the same machine that can remain connected, so netNamedPipe Binding is one possible way to go.
To make the thing a bit more fun I will create a little chat application. The server app will store connections from new clients, so when a client is sending a message, it will notify back all other clients connected to it. To achieve that I use an approach I exposed in a previous post which is WCF callbacks.
-
I – The Interface
The first thing to do is to define the interface client and server will use to communicate. A client must be able to send a message to the server and also to subscribe/unsubscribe to server callbacks:
namespace Interfaces
{
[ServiceContract(
SessionMode = SessionMode.Required,
CallbackContract = typeof(IChatCallback))]
public interface IChatService
{
[OperationContract]
void SendMessage(string user, string msg);
[OperationContract]
bool Subscribe();
[OperationContract]
bool Unsubscribe();
}
public interface IChatCallback
{
[OperationContract(IsOneWay = true)]
void OnNewMessage(string user, string msg);
}
}
-
II – The Server Application
The server needs to implement that interface. It will keep track of each incoming connection activated through the Subscribe method, so it can notify back each connected client through the callback channel:
[ServiceBehavior(
Name = "ServerSvc",
InstanceContextMode = InstanceContextMode.Single)]
-
class ServerSvc: IChatService
{
Dictionary<string, IChatCallback> _subscribers = null;
ServerControl _serverCtrl = null;
public ServerSvc(ServerControl serverCtrl)
{
_serverCtrl = serverCtrl;
_subscribers =
new Dictionary<string, IChatCallback>();
}
public void SendMessage(string user, string msg)
{
OperationContext ctx = OperationContext.Current;
foreach (var subscriber in _subscribers)
{
try
{
if (ctx.SessionId == subscriber.Key)
continue;
if (null != subscriber.Value)
{
Thread thread = new Thread(delegate()
{
subscriber.Value.OnNewMessage(user, msg);
});
thread.Start();
}
}
catch (Exception ex)
{
continue;
}
}
_serverCtrl.LogMessage("Message from " + user + ": " + msg);
}
public bool Subscribe()
{
try
{
OperationContext ctx = OperationContext.Current;
IChatCallback callback =
ctx.GetCallbackChannel<IChatCallback>();
if (!_subscribers.ContainsKey(ctx.SessionId))
{
_subscribers.Add(ctx.SessionId, callback);
_serverCtrl.LogMessage(
"New user connected: " + ctx.SessionId);
}
return true;
}
catch (Exception ex)
{
return false;
}
}
public bool Unsubscribe()
{
try
{
OperationContext ctx = OperationContext.Current;
if (!_subscribers.ContainsKey(ctx.SessionId))
return false;
_subscribers.Remove(ctx.SessionId);
_serverCtrl.LogMessage(
"User disconnected. Id:" + ctx.SessionId);
return true;
}
catch
{
return false;
}
}
}
We will host the server in an executable, so we need to use a ServiceHost to host our WCF service. This is also the place where we define which binding to use: this is typically done through the use of a config file, however in that simple case we can also do it directly through the code at runtime. This is the beauty of WCF:
ServerSvc svc = new ServerSvc(this);
_host = new ServiceHost(
svc,
new Uri[] { new Uri("net.pipe://localhost") });
_host.AddServiceEndpoint(
typeof(IChatService),
new NetNamedPipeBinding(), "ADNChatSrv");
_host.Open();
ClearMessages();
-
LogMessage("Server started ...");
-
-
III – The Client Application
-
The client needs to implement the callback interface to process notifications from the server:
class Callback: IChatCallback
{
Client _client;
public Callback(Client client)
{
_client = client;
}
public void OnNewMessage(string user, string msg)
{
_client.LogPeerMessage(
user + " says: " + Environment.NewLine + msg);
}
}
-
It then need to open a duplex channel so it can at the same time send messages to the server and receive callbacks:
try
{
_callback = new Callback(this);
DuplexChannelFactory<IChatService> factory =
new DuplexChannelFactory<IChatService>(
_callback,
new NetNamedPipeBinding(),
new EndpointAddress("net.pipe://localhost/ADNChatSrv"));
_chatSrv = factory.CreateChannel();
bool res = _chatSrv.Subscribe();
}
catch(Exception ex)
{
LogErrorMessage(ex.Message);
}
-
And that’s pretty much it! I was wrapping a little bit of UI around it to make it look more user friendly. The full project is attached at the bottom of that post.
I hope you find this useful.
Nice post, I bookmark your blog because I found very good information on your blog, Thanks for sharing more information. Regards vmware jobs in hyderabad
Posted by: meghana | 07/10/2017 at 03:02 AM