Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simple cross-platform process to process communication in Mono?

Tags:

c#

mono

ipc

I'm working on a Mono application that will run on Linux, Mac, and Windows, and need the ability for apps (on a single os) to send simple string messages to each other.

Specifically, I want a Single Instance Application. If a second instance is attempted to be started, it will instead send a message to the single instance already running.

DBus is out, as I don't want to have that be an additional requirement. Socket communication seems to be hard, as windows seems to not allow permission to connect. Memory Mapped Files seems not to be supported in Mono. Named Pipes appears not to be supported in Mono. IPC seems not to be supported on Mono.

So, is there a simple method to send string messages on a single machine to a server app that works on each os, without requiring permissions, or additional dependencies?

like image 734
Doug Blank Avatar asked Mar 20 '11 02:03

Doug Blank


People also ask

Which is inter process communication?

What is interprocess communication? Official definition: Interprocess communication (IPC) is used for programs to communicate data to each other and to synchronize their activities. Semaphores, shared memory, and internal message queues are common methods of interprocess communication.

What is inter process communication using pipes?

A Pipe is a technique used for inter process communication. A pipe is a mechanism by which the output of one process is directed into the input of another process. Thus it provides one way flow of data between two related processes.

What is inter process communication in Windows?

The Windows operating system provides mechanisms for facilitating communications and data sharing between applications. Collectively, the activities enabled by these mechanisms are called interprocess communications (IPC).


3 Answers

On my ubuntu (10.10 mono version: 2.6.7) I've tried using WCF for interprocess communication with BasicHttpBinding, NetTcpBinding and NetNamedPipeBinding. First 2 worked fine, for NetNamedPipeBinding I got an error:

Channel type IDuplexSessionChannel is not supported

when calling ChannelFactory.CreateChannel() method.

I've also tried using Remoting (which is a legacy technology since WCF came out) with IpcChannel; example from this msdn page started and worked without problems on my machine.

I suppose you shouldn't have problems using WCF or Remoting on Windows either, not sure about Mac though, don't have any of those around to test. Let me know if you need any code examples.

hope this helps, regards

like image 145
serge_gubenko Avatar answered Nov 08 '22 22:11

serge_gubenko


I wrote about this on the mono-dev mailing list. Several general-purpose inter-process messaging systems were considered, including DBus, System.Threading.Mutex class, WCF, Remoting, Named Pipes... The conclusions were basically mono doesn't support Mutex class (works for inter-thread, not for inter-process) and there's nothing platform agnostic available.

I have only been able to imagine three possible solutions. All have their drawbacks. Maybe there's a better solution available, or maybe just better solutions for specific purposes, or maybe there exist some cross-platform 3rd party libraries you could include in your app (I don't know.) But these are the best solutions I've been able to find so far:

  • Open or create a file in a known location, with exclusive lock. (FileShare.None). Each application tries to open the file, do its work, and close the file. If failing to open, Thread.Sleep(1) and try again. This is kind of ghetto, but it works cross-platform to provide inter-process mutex.
  • Sockets. First application listens on localhost, some high numbered port. Second application attempts to listen on that port, fails to open (because some other process already has it) so second process sends a message to the first process, which is already listening on that port.
  • If you have access to a transactional database, or message passing system (sqs, rabbitmq, etc) use it.
  • Of course, you could detect which platform you're on, and then use whatever works on that platform.
like image 25
Edward Ned Harvey Avatar answered Nov 08 '22 23:11

Edward Ned Harvey


Solved my problem with two techniques: a named mutex (so that the app can be run on the same machine by different users), and a watcher on a message file. The file is opened and written to for communication. Here is a basic solution, written in IronPython 2.6:

(mutex, locked) = System.Threading.Mutex(True, "MyApp/%s" % System.Environment.UserName, None)
if locked:
    watcher = System.IO.FileSystemWatcher()
    watcher.Path = path_to_user_dir
    watcher.Filter = "messages"
    watcher.NotifyFilter = System.IO.NotifyFilters.LastWrite
    watcher.Changed += handleMessages
    watcher.EnableRaisingEvents = True
else:
    messages = os.path.join(path_to_user_dir, "messages")
    fp = file(messages, "a")
    fp.write(command)
    fp.close()
    sys.exit(0)
like image 1
Doug Blank Avatar answered Nov 08 '22 21:11

Doug Blank