我正在使用Lukas Thomsen's命名管道示例来创建C ++中的管道服务器和Java中的读者。
在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中命名管道的正确方法是什么?
答案 0 :(得分:0)
出现此问题的原因是Windows上的File.exists()
是使用对CreateFile
,GetFileInformationByHandle
和CloseHandle
的一系列本机函数调用实现的。请参阅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);
}
}
(显然你可能不想在实践中永远循环,但问题中的代码确实如此。)