命名管道在检查它是否存在于Java时连接

时间:2016-03-14 17:39:03

标签: eclipse pipe ipc named-pipes java-io

我正在使用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中命名管道的正确方法是什么?

1 个答案:

答案 0 :(得分:0)

出现此问题的原因是Windows上的File.exists()是使用对CreateFileGetFileInformationByHandleCloseHandle的一系列本机函数调用实现的。请参阅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);
    }
}

(显然你可能不想在实践中永远循环,但问题中的代码确实如此。)