命名管道已连接,同时检查它是否存在于 Java
Named pipe is connected while checking if it exists from Java
我正在使用 Lukas Thomsen's 命名管道示例在 C++ 中创建一个管道服务器,在 Java 中创建一个 reader。
在 Java 方面,我想等到 C++ 服务器创建命名管道。
File file = new File("\\.\pipe\Pipe");
while(!file.exists());
InputStream input = new FileInputStream(file);
但是,file.exists() 以某种方式连接命名管道并实例化 FileInputStream 抛出以下异常:
java.io.FileNotFoundException: \.\pipe\Pipe (All pipe instances are busy)
at java.io.FileInputStream.open0(Native Method)
at java.io.FileInputStream.open(Unknown Source)
at java.io.FileInputStream.<init>(Unknown Source)
这是 c++ 服务器的片段:
int main(void)
{
HANDLE hPipe;
char buffer[1024];
DWORD dwRead;
hPipe = CreateNamedPipe(TEXT("\\.\pipe\Pipe"),
PIPE_ACCESS_DUPLEX | PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, // FILE_FLAG_FIRST_PIPE_INSTANCE is not needed but forces CreateNamedPipe(..) to fail if the pipe already exists...
PIPE_WAIT,
1,
1024 * 16,
1024 * 16,
NMPWAIT_USE_DEFAULT_WAIT,
NULL);
while (hPipe != INVALID_HANDLE_VALUE)
{
if (ConnectNamedPipe(hPipe, NULL) != FALSE) // wait for someone to connect to the pipe
{
cout<<"connected";
//do amazing stuff after being connected.
}
DisconnectNamedPipe(hPipe);
}
return 0;
}
那么在 Java 中等待命名管道而不抛出此错误的正确方法是什么?
出现此问题的原因是 Windows 上的 File.exists()
是使用对 CreateFile
, GetFileInformationByHandle
and CloseHandle
. See the getFileInformation
function in the Java source code 的一系列本机函数调用实现的。从命名管道的角度来看,这很糟糕,因为在 Windows 上,必须在使用之间重置命名管道,并且该本机函数中的 CreateFile
调用算作一次使用。
解决方案是在 Java 端打开命名管道时请求原谅而不是许可。大致如下:
File file = new File("\\.\pipe\Pipe");
while (true) {
try {
return new FileInputStream(file);
} catch (IOException e) {
Thread.sleep(20);
}
}
(显然你可能不想在实践中永远循环,但问题中的代码确实如此。)
我正在使用 Lukas Thomsen's 命名管道示例在 C++ 中创建一个管道服务器,在 Java 中创建一个 reader。
在 Java 方面,我想等到 C++ 服务器创建命名管道。
File file = new File("\\.\pipe\Pipe");
while(!file.exists());
InputStream input = new FileInputStream(file);
但是,file.exists() 以某种方式连接命名管道并实例化 FileInputStream 抛出以下异常:
java.io.FileNotFoundException: \.\pipe\Pipe (All pipe instances are busy)
at java.io.FileInputStream.open0(Native Method)
at java.io.FileInputStream.open(Unknown Source)
at java.io.FileInputStream.<init>(Unknown Source)
这是 c++ 服务器的片段:
int main(void)
{
HANDLE hPipe;
char buffer[1024];
DWORD dwRead;
hPipe = CreateNamedPipe(TEXT("\\.\pipe\Pipe"),
PIPE_ACCESS_DUPLEX | PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, // FILE_FLAG_FIRST_PIPE_INSTANCE is not needed but forces CreateNamedPipe(..) to fail if the pipe already exists...
PIPE_WAIT,
1,
1024 * 16,
1024 * 16,
NMPWAIT_USE_DEFAULT_WAIT,
NULL);
while (hPipe != INVALID_HANDLE_VALUE)
{
if (ConnectNamedPipe(hPipe, NULL) != FALSE) // wait for someone to connect to the pipe
{
cout<<"connected";
//do amazing stuff after being connected.
}
DisconnectNamedPipe(hPipe);
}
return 0;
}
那么在 Java 中等待命名管道而不抛出此错误的正确方法是什么?
出现此问题的原因是 Windows 上的 File.exists()
是使用对 CreateFile
, GetFileInformationByHandle
and CloseHandle
. See the getFileInformation
function in the Java source code 的一系列本机函数调用实现的。从命名管道的角度来看,这很糟糕,因为在 Windows 上,必须在使用之间重置命名管道,并且该本机函数中的 CreateFile
调用算作一次使用。
解决方案是在 Java 端打开命名管道时请求原谅而不是许可。大致如下:
File file = new File("\\.\pipe\Pipe");
while (true) {
try {
return new FileInputStream(file);
} catch (IOException e) {
Thread.sleep(20);
}
}
(显然你可能不想在实践中永远循环,但问题中的代码确实如此。)