使用 Windows 命名管道进行 IPC 的有效方法

An efficient way to use Windows Named Pipe for IPC

我正在使用 jna 模块连接两个都执行 FFMPEG 命令的进程。在服务器端将 FFMPEG 命令的 SDTOUT 发送到 NampedPipe,并从该 NampedPipe 接收 STDIN 以在客户端接收其他 FFMPEG 命令。

这就是我捕获 STDOUT 并发送到服务器端管道的方式:

InputStream out = inputProcess.getInputStream();
byte[] buffer = new byte[maxBufferSize];
while (inputProcess.isAlive()) {
     int no = out.available();
     if (no > 0 && no > maxBufferSize) {
        int n = out.read(buffer, 0,maxBufferSize);
        IntByReference lpNumberOfBytesWritten = new IntByReference(maxBufferSize);
        Kernel32.INSTANCE.WriteFile(pipe, buffer, buffer.length, lpNumberOfBytesWritten, null);
     }
}

这就是我捕获 STDIN 并将其提供给客户端的方式:

OutputStream in = outputProcess.getOutputStream();
while (pipeOpenValue >= 1 && outputProcess.isAlive() && ServerIdState) {
      // read from pipe
      resp = Kernel32.INSTANCE.ReadFile(handle, readBuffer,readBuffer.length, lpNumberOfBytesRead, null);
      // Write to StdIn inputProcess
      if (outputProcess != null) {
          in.write(readBuffer);
          in.flush();
      }
      // check pipe status
      Kernel32.INSTANCE.GetNamedPipeHandleState(handle, null,PipeOpenStatus, null, null, null, 2048);
      pipeOpenValue = PipeOpenStatus.getValue();
      WinDef.ULONGByReference ServerId = new WinDef.ULONGByReference();
      ServerIdState = Kernel32.INSTANCE.GetNamedPipeServerProcessId(handle, ServerId);
}

但是我遇到了两个问题:

  1. 高 CPU 使用率由于在服务器和客户端中迭代两个循环。 (通过 VisualVM 分析资源找到)
  2. 比仅在命令提示符下使用常规 | 连接两个 FFMPEG 命令更慢。速度取决于缓冲区大小,但大缓冲区大小会阻止操作,而小缓冲区大小会进一步降低速度。

问题:

  1. 有没有办法不以字节块的形式发送和接收?只需将 STDOUT 流式传输到 Namedpipe 并在客户端中捕获它。 (消除两个循环)
  2. 如果我不能使用 NampedPipe,是否有任何其他方法可以连接在不同 java 模块但在同一台机器上运行的两个 FFMPEG 进程?

谢谢

似乎您一直在服务器端轮询进程状态标准输入,而不等待任何事件或使线程休眠。 可能您想在这里看看: Concurrent read/write of named pipe in Java (on windows)

干杯!