如何使用标准输入和标准输出在 C# 和 ruby​​ 进程之间进行通信

Posted

技术标签:

【中文标题】如何使用标准输入和标准输出在 C# 和 ruby​​ 进程之间进行通信【英文标题】:How to communicate between C# and ruby processes using stdin and stdout 【发布时间】:2014-04-02 20:55:34 【问题描述】:

尝试不同的进程间通信方法。

我有一个 C# 应用程序,它生成一个 ruby​​ 进程并重定向 ruby​​ 进程的 stdin 和 stdout,以便 C# 应用程序可以向 ruby​​ 进程发送指令,而 ruby​​ 进程可以发回一些东西。

鲁比:

cmd = STDIN.read
p "Test command received!" if cmd.downcase == "test"

C#

static void Main(string[] args)

  ProcessStartInfo procInfo = new ProcessStartInfo("ruby");
  procInfo.Arguments = "stdinTest.rb";
  procInfo.UseShellExecute = false;
  procInfo.RedirectStandardInput = true;
  procInfo.RedirectStandardOutput = true;

  proc = new Process();
  proc.StartInfo = procInfo;
  proc.Start();
  proc.StandardInput.Write("test");
  proc.StandardInput.Close();

  Console.WriteLine(proc.StandardOutput.ReadLine());

这假定 Ruby 位于 sys 路径上,并且 ruby​​ 脚本与 C# 应用程序位于同一文件夹中。

当我运行 C# 应用程序时,它会打印出“收到测试命令!”正如预期的那样。

但是,值得怀疑的一件事是我正在关闭进程的标准输入……这意味着我不能再写它了。

如果我删除 close,它就会挂起。大概是因为 Ruby 没有得到一个预期的字符来告诉它停止阅读。

如果我使用flush,它没有任何区别。

这次交流有什么问题? C# 是否有不同的方式将数据发送到 ruby​​ 的 STDIN? Ruby 应该以不同的方式从 STDIN 读取数据吗?

【问题讨论】:

【参考方案1】:

STDIN 是一个流,STDIN.read 正在尝试读取到流的末尾。首先发送您的数据长度并使用read 长度:

数据包:0008ABCDEFGH(在现实生活中应该使用二进制长度)

length = STDIN.read(4).to_i
data = STDIN.read(length)

那么你不必关闭它,可以发送另一个数据包。

【讨论】:

这个想法是有道理的。如果我只是简单地将长度写为 C# 中的整数,那么长度是基于位数的。我必须以某种方式对其进行序列化,或者作为表示 4 字节整数的字节流,以便 Ruby 始终可以期望长度存储在 4 个字节中。

以上是关于如何使用标准输入和标准输出在 C# 和 ruby​​ 进程之间进行通信的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C# 中的同一线程上收听标准输入和套接字?

使用带有标准输入和标准输出重定向的 2 进程管道时如何避免标准输入上的重复输入

如何在 Windows 上的 CreateProcess() 中不继承标准输入、标准输出和标准错误

使用文件作为子进程的标准输入和标准输出

如何让 ruby​​-prof 忽略 Ruby 核心/标准库/gem 方法?

如何在 Visual Studio Code 任务中使用标准输入/标准输出重定向?