The name of it is inter-process communication (IPC: Interprocess Communications).
Can be done in many ways:
- Sockets
- Named Pipes
- Files mapped in memory
- among others
I will show you how to do using Named Pipes, based on the this response from the SOEN, slightly altered to be functional (because the guy there did not test the answer, but I did).
The example consists of two console applications communicating, but could be any kind of application, ie, if it applies perfectly to your case.
Are two main classes:
PipeServer
: allows serving multiple clients with the same named pipe
PipeClient
: allows connecting to a named pipe server
The example consists in exchanging numbers between the client and the server, and each part increments the number with a random from 0 to 10 and sends it back to the other side.
You can start the server, and then start multiple clients. The server will print on the screen the numbers it receives and sends to the clients, and the clients will do the same.
Namedpipesserver.csproj
Pipeserver.Cs
using System;
using System.IO.Pipes;
using System.Threading;
namespace NamedPipesServer
{
public class PipeServer
{
private Thread runningThread;
private volatile bool pareAssimQuePossivel;
public string PipeName { get; private set; }
public PipeServer(string pipeName)
{
this.PipeName = pipeName;
}
private void ServerLoop()
{
while (!this.pareAssimQuePossivel)
this.ProcessNextClient();
}
public void Iniciar()
{
this.runningThread = new Thread(this.ServerLoop);
this.runningThread.Start();
}
public void Parar()
{
this.pareAssimQuePossivel = true;
}
public void Abortar()
{
this.runningThread.Abort();
}
private void ProcessClientThread(object o)
{
using (var pipeStream = (NamedPipeServerStream)o)
{
try
{
this.OnProcessClient(pipeStream);
}
finally
{
pipeStream.WaitForPipeDrain();
if (pipeStream.IsConnected)
pipeStream.Disconnect();
}
}
}
public event ProcessClient ProcessClient;
protected virtual void OnProcessClient(NamedPipeServerStream o)
{
if (this.ProcessClient != null)
this.ProcessClient(this, o);
}
private void ProcessNextClient()
{
try
{
var pipeStream = new NamedPipeServerStream(this.PipeName, PipeDirection.InOut, -1);
pipeStream.WaitForConnection();
// Spawn a new thread for each request and continue waiting
var t = new Thread(this.ProcessClientThread);
t.Start(pipeStream);
}
catch (Exception e)
{
// If there are no more available connections
// (254 is in use already) then just
// keep looping until one is available
}
}
public void EsperarAteDesconectar()
{
if (this.runningThread != null)
this.runningThread.Join();
}
}
public delegate void ProcessClient(PipeServer sender, NamedPipeServerStream stream);
}
Program.Cs
using System;
using System.IO;
using System.IO.Pipes;
using System.Threading;
namespace NamedPipesServer
{
static class Program
{
static void Main(string[] args)
{
var server = new PipeServer("MeuNamedPipe");
server.ProcessClient += ProcessClient;
server.Iniciar();
server.EsperarAteDesconectar();
}
private static volatile int number;
private static ConsoleColor[] colors = new []
{
ConsoleColor.Blue,
ConsoleColor.Cyan,
ConsoleColor.Green,
ConsoleColor.Magenta,
ConsoleColor.Red,
ConsoleColor.White,
ConsoleColor.Yellow,
};
private static object locker = new object();
private static void ProcessClient(PipeServer sender, NamedPipeServerStream stream)
{
var reader = new StreamReader(stream);
var writer = new StreamWriter(stream);
var random = new Random();
var color = colors[Interlocked.Increment(ref number)];
writer.WriteLine(color);
int num = 0;
while (true)
{
num += random.Next(10);
lock (locker)
{
Console.ForegroundColor = color;
Console.WriteLine("Send: " + num);
}
writer.WriteLine(num);
writer.Flush();
stream.WaitForPipeDrain();
Thread.Sleep(1000);
var recv = reader.ReadLine();
lock (locker)
{
Console.ForegroundColor = color;
Console.WriteLine("Received: " + recv);
}
var recvNum = int.Parse(recv);
num = recvNum;
Thread.Sleep(1000);
}
}
}
}
Namedpipeclient.csproj
Pipeclient.Cs
using System;
using System.IO.Pipes;
using System.Threading;
namespace NamedPipeClient
{
public class PipeClient
{
private Thread runningThread;
private volatile bool pareAssimQuePossivel;
public string PipeName { get; private set; }
public bool PareAssimQuePossivel
{
get { return this.pareAssimQuePossivel; }
}
public PipeClient(string pipeName)
{
this.PipeName = pipeName;
}
private void ClientProcessorThread()
{
while (true)
{
try
{
using (var pipeStream = new NamedPipeClientStream(".", this.PipeName, PipeDirection.InOut))
{
pipeStream.Connect(10000);
try
{
this.OnProcessServer(pipeStream);
}
finally
{
pipeStream.WaitForPipeDrain();
}
}
}
catch (Exception e)
{
// If there are no more available connections
// (254 is in use already) then just
// keep looping until one is available
}
}
}
public void Iniciar()
{
this.runningThread = new Thread(this.ClientProcessorThread);
this.runningThread.Start();
}
public void Parar()
{
this.pareAssimQuePossivel = true;
}
public void Abortar()
{
this.runningThread.Abort();
}
public event ProcessServer ProcessServer;
protected virtual void OnProcessServer(NamedPipeClientStream o)
{
if (this.ProcessServer != null)
this.ProcessServer(this, o);
}
public void EsperarAteDesconectar()
{
if (this.runningThread != null)
this.runningThread.Join();
}
}
public delegate void ProcessServer(PipeClient sender, NamedPipeClientStream stream);
}
Program.Cs
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Pipes;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace NamedPipeClient
{
static class Program
{
static void Main(string[] args)
{
var client = new PipeClient("MeuNamedPipe");
client.ProcessServer += ProcessServer;
client.Iniciar();
client.EsperarAteDesconectar();
}
private static void ProcessServer(PipeClient sender, NamedPipeClientStream stream)
{
var reader = new StreamReader(stream);
var writer = new StreamWriter(stream);
var random = new Random();
var colorStr = reader.ReadLine();
var color = (ConsoleColor)Enum.Parse(typeof(ConsoleColor), colorStr);
Console.ForegroundColor = color;
int num;
while (true)
{
var recv = reader.ReadLine();
Console.WriteLine("Received: " + recv);
var recvNum = int.Parse(recv);
num = recvNum;
Thread.Sleep(1000);
num += random.Next(10);
Console.WriteLine("Send: " + num);
writer.WriteLine(num);
writer.Flush();
stream.WaitForPipeDrain();
Thread.Sleep(1000);
}
}
}
}
I was told to do it by Startup. I didn’t mean it very well. Vicê has heard?
– Railson Lima