命名管道C#客户端无法连接到C++服务器

3
我正在尝试让一个C++应用程序在特定操作发生时通知一个C#应用程序。我尝试使用命名管道来实现这一点。
我已经在C++应用程序上设置了一个命名管道服务器,它似乎正在工作(命名管道被创建 - 它出现在PipeList检索到的列表中),并在C#应用程序上设置了一个命名管道客户端,但失败了:C#客户端代码的第一行给出了“管道句柄未设置。你的PipeStream实现是否调用了InitializeHandle?”错误,第二行抛出了“拒绝访问路径”的异常。
我错在哪里? C++服务器代码
CString namedPipeName = "\\\\.\\pipe\\TitleChangePipe";

HANDLE pipe = CreateNamedPipe(namedPipeName, PIPE_ACCESS_INBOUND , PIPE_WAIT, 1, 1024, 1024, 120 * 1000, NULL);
if (pipe == INVALID_HANDLE_VALUE) {
    MessageBox(NULL, "Pipe Could Not be Established.", "Error: TCM", MB_ICONERROR);
    return -1;
}

char line[512]; DWORD numRead;

while (true)//just keep doing this
{
    numRead = 1;
    while ((numRead < 10 || numRead > 511) && numRead > 0)
    {
        if (!ReadFile(pipe, line, 512, &numRead, NULL) || numRead < 1) {//Blocking call
            CloseHandle(pipe);                                          //If something went wrong, reset pipe
            pipe = CreateNamedPipe(namedPipeName, PIPE_ACCESS_INBOUND , PIPE_WAIT, 1, 1024, 1024, 120 * 1000, NULL);
            ConnectNamedPipe(pipe, NULL);
            if (pipe == INVALID_HANDLE_VALUE) {
                MessageBox(NULL, "Pipe Could Not be Established.", "Error: TCM", MB_ICONERROR);
                return -1; }
            numRead = 1;
        }
    }
    line[numRead] = '\0';   //Terminate String
}   

CloseHandle(pipe);

C#客户端代码

var client = new NamedPipeClientStream(".", "TitleChangePipe", PipeDirection.InOut);
client.Connect();
var reader = new StreamReader(client);
var writer = new StreamWriter(client);

while (true)
{
    var input = Console.ReadLine();
    if (String.IsNullOrEmpty(input))
         break;
    writer.WriteLine(input);
    writer.Flush();
    Console.WriteLine(reader.ReadLine());
}
1个回答

3
创建命名管道的参数不正确。
首先,你希望在管道上进行读写操作,因此要使用的标志是:PIPE_ACCESS_DUPLEX。
然后,在这里你是以同步模式发送消息。使用这些标志:PIPE_WAIT | PIPE_TYPE_MESSAGE。
最后,你只允许在机器上有一个此管道的实例。显然,你需要至少两个:一个用于服务器,一个用于客户端。我建议只使用无限制标志:PIPE_UNLIMITED_INSTANCES。
HANDLE pipe = CreateNamedPipe(namedPipeName, PIPE_ACCESS_DUPLEX, \
                              PIPE_WAIT | PIPE_TYPE_MESSAGE, PIPE_UNLIMITED_INSTANCES, \
                              1024, 1024, 120 * 1000, NULL);

在服务器创建管道后,您应在使用它之前等待对该管道的连接: https://msdn.microsoft.com/en-us/library/windows/desktop/aa365146(v=vs.85).aspx

谢谢您的回复和解释。我已经更改了CreateNamedPipe的实例,以便按照建议的方式使用变量。就在使用管道之前等待连接方面,据我所知,这就是ConnectNamedPipe所做的。话虽如此,我不再遇到“拒绝访问路径”的异常,但仍会在客户端代码的第一行收到“未设置管道句柄。您的PipeStream实现是否调用InitializeHandle” 的错误提示。 - Claudiu
1
是的,这就是ConnectNamedPipe所做的事情,要使用它而不仅仅在循环中使用!再次检查管道的名称,因为带有“\pipe”前缀可能会让人感到困惑。我还发现了一个类似的线程:https://dev59.com/xmTWa4cB1Zd3GeqPBDYj。;] - Tezirg
谢谢!我也应该在循环外部使用它,在管道创建后,就像你提到的那样。现在运行得很好 :) - Claudiu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接