Как общаться между процессами C# и ruby ​​с помощью stdin и stdout

Пробуем разные методы межпроцессного взаимодействия.

У меня есть приложение С#, которое порождает процесс ruby ​​​​и перенаправляет stdin и stdout процесса ruby, чтобы приложение 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#.

Когда я запускаю приложение С#, оно выводит «Тестовая команда получена!» как и ожидалось.

Однако вызывает сомнения тот факт, что я закрываю стандартный ввод процесса... что означает, что я больше не могу писать в него.

Если я уберу close, он просто зависнет. Предположительно, потому что Ruby не получает ожидаемого символа, который говорит ему прекратить чтение.

Если я использую flush, это не имеет значения.

В чем проблема с этим обменом?
Есть ли в C# другой способ отправки данных в STDIN ruby?
Должен ли Ruby читать из STDIN по-другому?


person MxLDevs    schedule 02.04.2014    source источник


Ответы (1)


STDIN — это поток, а STDIN.read пытается прочитать до конца потока. Сначала отправьте длину ваших данных и используйте read с длиной:

Пакет: 0008ABCDEFGH (в реальной жизни вы должны использовать двоичную длину)

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

Тогда вам не нужно закрывать его и вы можете отправить другой пакет (пакеты).

person Victor Moroz    schedule 02.04.2014
comment
Идея имеет смысл. Если я просто запишу длину в виде целого числа в C#, длина будет основана на количестве цифр. Мне пришлось бы каким-то образом сериализовать его, либо как поток байтов, представляющий 4-байтовое целое число, чтобы Ruby всегда мог ожидать, что длина будет храниться в 4 байтах. - person MxLDevs; 03.04.2014