一个高效的使用Windows命名管道进行进程间通信的方法。

huangapple go评论78阅读模式
英文:

An efficient way to use Windows Named Pipe for IPC

问题

以下是翻译的内容:

我正在使用jna模块来连接两个同时执行FFMPEG命令的进程。在服务器端将FFMPEG命令的STDOUT发送到NamedPipe,并在客户端从该NamedPipe接收用于其他FFMPEG命令的STDIN

以下是我如何在服务器端捕获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) {
      // 从管道读取
      resp = Kernel32.INSTANCE.ReadFile(handle, readBuffer, readBuffer.length, lpNumberOfBytesRead, null);
      // 写入到inputProcess的StdIn
      if (outputProcess != null) {
          in.write(readBuffer);
          in.flush();
      }
      // 检查管道状态
      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. 如果我不能使用NamedPipe,是否有其他方法可以连接在同一台机器上运行但位于不同Java模块中的两个FFMPEG进程?

谢谢

英文:

I am using jna module to connect two processes that both perform FFMPEG commands. Send SDTOUT of FFMPEG command on the server side to NampedPipe and receive STDIN from that NampedPipe for other FFMPEG command on the Client side.

this is how I capture STDOUT and send into the pipe in server Side:

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);
     }
}

And this is how I capture STDIN and feed it to the Client Side:

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);
}

But I faced two problems:

  1. High CPU usage due to iterating two loops in Server and Client. (find by profiling resources by VisualVM)
  2. Slower operation than just connecting two FFMPEG command with regular | in command prompt. Speed depends on buffer size but large buffer size blocks operation and small buffer size reduce speed further.

Questions:

  1. Is there any way not to send and receive in chunks of bytes? Just stream STDOUT to the Namedpipe and capture it in Client. (Eliminate two Loops)
  2. If I cant use NampedPipe, is there any other way to Connect two FFMPEG process that runs in different java modules but in the same machine?

Thanks

答案1

得分: 0

好的,以下是您要翻译的内容:

似乎您在服务器端不断轮询进程状态的标准输入,而不等待任何事件或暂停线程。可能您想在这里查看:https://stackoverflow.com/questions/4974989/concurrent-read-write-of-named-pipe-in-java-on-windows

祝好!

英文:

Seems like you're constantly polling process states stdin on server side without waiting for any events or sleeping the thread.
Probably you want to take a look here:
https://stackoverflow.com/questions/4974989/concurrent-read-write-of-named-pipe-in-java-on-windows

Cheers!

huangapple
  • 本文由 发表于 2020年7月26日 16:17:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/63097736.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定