将 Windows 命名管道用于 IPC 的一种有效方法
Posted
技术标签:
【中文标题】将 Windows 命名管道用于 IPC 的一种有效方法【英文标题】:An efficient way to use Windows Named Pipe for IPC 【发布时间】:2020-07-26 08:17:08 【问题描述】:我正在使用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);
但我遇到了两个问题:
-
由于在服务器和客户端中迭代两个循环,CPU 使用率很高。 (通过 VisualVM 分析资源来查找)
比在命令提示符中使用常规
|
连接两个 FFMPEG 命令更慢。速度取决于缓冲区大小,但较大的缓冲区会阻止操作,而较小的缓冲区会进一步降低速度。
问题:
-
有什么方法可以不发送和接收字节块吗?只需将
STDOUT
流式传输到命名管道并在客户端中捕获它。 (消除两个循环)
如果我不能使用 NampedPipe,有没有其他方法可以连接两个在不同 java 模块中但在同一台机器上运行的 FFMPEG 进程?
谢谢
【问题讨论】:
【参考方案1】:似乎您一直在服务器端轮询进程状态标准输入,而无需等待任何事件或使线程休眠。 可能你想看看这里: Concurrent read/write of named pipe in Java (on windows)
干杯!
【讨论】:
很抱歉回答迟了。谢谢你。你的建议解决了我的问题以上是关于将 Windows 命名管道用于 IPC 的一种有效方法的主要内容,如果未能解决你的问题,请参考以下文章
dotnet 替换 ASP.NET Core 的底层通讯为命名管道的 IPC 库