在 Mono 中处理通信的简单跨平台流程?

发布于 2024-10-25 04:34:23 字数 335 浏览 5 评论 0原文

我正在开发一个将在 Linux、Mac 和 Windows 上运行的 Mono 应用程序,并且需要应用程序(在单个操作系统上)能够相互发送简单的字符串消息。

具体来说,我想要一个单实例应用程序。如果尝试启动第二个实例,它将改为向已运行的单个实例发送消息。

DBus 已经退出,因为我不想让它成为一个额外的要求。 套接字通信似乎很难,因为 Windows 似乎不允许连接权限。 Mono 似乎不支持内存映射文件。 Mono 似乎不支持命名管道。 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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

扛起拖把扫天下 2024-11-01 04:34:27

此答案不适用于所有平台

使用两种技术解决了我的问题:命名互斥体(以便应用程序可以由不同用户在同一台​​计算机上运行)和消息文件上的观察程序。该文件被打开并写入以进行通信。这是一个用 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)

THIS ANSWER DOESN'T WORK FOR ALL PLATFORMS

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)
过度放纵 2024-11-01 04:34:26

我在 mono-dev 邮件列表上写了相关内容。考虑了几种通用的进程间消息系统,包括DBus、System.Threading.Mutex类、WCF、Remoting、Named Pipes...结论基本上是mono 不支持 Mutex 类 (适用于线程间,不适用于进程间)和 没有任何平台不可知的可用

我只能想象三种可能的解决方案。都有其缺点。也许有更好的解决方案可用,或者可能只是针对特定目的的更好的解决方案,或者也许存在一些可以包含在您的应用程序中的跨平台第三方库(我不知道。)但是这些是迄今为止我能找到的最好的解决方案:

  • 使用独占锁在已知位置打开或创建文件。 (文件共享。无)。每个应用程序都会尝试打开文件、执行其工作并关闭文件。如果无法打开,请Thread.Sleep(1)并重试。这是一种贫民窟,但它可以跨平台工作以提供进程间互斥。
  • 插座。第一个应用程序在本地主机上侦听一些高编号端口。第二个应用程序尝试侦听该端口,但无法打开(因为其他进程已经拥有该端口),因此第二个进程向第一个进程发送一条消息,该进程已经在该端口上侦听。
  • 如果您有权访问事务数据库或消息传递系统(sqs、rabbitmq 等),请使用它。
  • 当然,您可以检测您所在的平台,然后使用该平台上可用的任何内容。

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.
恰似旧人归 2024-11-01 04:34:26

由于您需要 IPC 的简单原因,我会寻找另一种解决方案。

该代码已被证实可以在 Linux 和 Windows 上运行。应该也适用于 Mac:

    public static IList Processes()
    {
        IList<Process> processes = new List<Process>();
        foreach (System.Diagnostics.Process process in System.Diagnostics.Process.GetProcesses())
        {
            Process p = new Process();
            p.Pid = process.Id;
            p.Name = process.ProcessName;

            processes.Add(p);
        }
        return processes;
    }

只需遍历列表并查找您自己的 ProcessName。

要将消息发送到您的应用程序,只需使用 MyProcess.StandardInput 写入应用程序标准输入。不过,这只适用于假设您的应用程序是 GUI 应用程序。

如果您遇到问题,那么您可以使用专门的“锁定”文件。使用 FileSystemWatcher 类,您可以检查它何时发生变化。这样,第二个实例可以在文件中写入一条消息,然后第一个实例注意到它发生了更改,并且可以读取文件的内容以获取消息。

For your simple reason for needing IPC, I'd look for another solution.

This code is confirmed to work on Linux and Windows. Should work on Mac as well:

    public static IList Processes()
    {
        IList<Process> processes = new List<Process>();
        foreach (System.Diagnostics.Process process in System.Diagnostics.Process.GetProcesses())
        {
            Process p = new Process();
            p.Pid = process.Id;
            p.Name = process.ProcessName;

            processes.Add(p);
        }
        return processes;
    }

Just iterate through the list and look for your own ProcessName.

To send a message to your application, just use MyProcess.StandardInput to write to the applications standard input. This only works assuming your application is a GUI application though.

If you have problems with that, then you could maybe use a specialized "lock" file. Using the FileSystemWatcher class you can check when it changes. This way the second instance could write a message in the file and then the first instance notice that it changes and can read in the contents of the file to get a message.

岁月静好 2024-11-01 04:34:25

在我的 ubuntu (10.10 单声道版本:2.6.7)上,我尝试使用 WCF 用于与 BasicHttpBinding、NetTcpBinding 和 NetNamedPipeBinding 进行进程间通信。前 2 个工作正常,对于 NetNamedPipeBinding 我收到错误:

通道类型 IDuplexSessionChannel 是
不支持

调用 ChannelFactory.CreateChannel() 方法时

。我还尝试过使用 Remoting (是自 WCF 出现以来的遗留技术)和 IpcChannel;此 msdn 页面 中的示例在我的机器上启动并运行没有问题。

我想您在 Windows 上使用 WCF 或远程处理也不会有问题,但不确定 Mac 是否如此,因为没有任何可供测试的工具。如果您需要任何代码示例,请告诉我。

希望这有帮助,问候

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文