从 NamedPipeClientStream 调用命名管道时未连接

Posted

技术标签:

【中文标题】从 NamedPipeClientStream 调用命名管道时未连接【英文标题】:Named Pipe Not connecting when being called from NamedPipeClientStream 【发布时间】:2015-05-21 22:03:54 【问题描述】:

在 IPC 代码中,如果我通过调用 CreateFile 使用 Win32 API 从命名管道获取句柄,一切正常。如果我使用NamedPipeClientStream 做同样的事情,它不想连接。

工作版

[DllImport("kernel32.dll")]
internal static extern SafePipeHandle CreateFile(
          string lpFileName,
          uint dwDesiredAccess,
          uint dwShareMode,
          IntPtr securityAttributes,
          uint dwCreationDisposition,
          uint dwFlagsAndAttributes,
          IntPtr hTemplateFile);        

public openPipe()


     SafePipeHandle localDeviceHandle;
     // Second Paameter is READ/WRITE Access, Fifth Parameter Open Existing 
     // This was done for brevity of the example.
     localDeviceHandle = FileApi.CreateFile("\\\\.\\SeaMAC0", 
                                            (uint)3, 
                                            0, 
                                            IntPtr.Zero, 
                                            (uint)3, 
                                            (uint)FileApi.FileAttribute.Normal, 
                                            IntPtr.Zero);

不工作

public openPipe()


  SeaLevelNamedPipe = new NamedPipeClientStream("SeaMAC0");

  /*or SeaLevelNamedPipe = new NamedPipeClientStream(".","SeaMAC0");*/

   SeaLevelNamedPipe.Connect(); //It will hang here for ever   


这里的代码远未完成,为简洁起见。它们的功能不应该一样吗?

我无权访问服务器管道代码,因为这是由第三方开发的。

【问题讨论】:

【参考方案1】:

在您的第一个“this works”示例中,您没有为 lpFileName 参数使用有效的命名管道名称。这:"\\\\.\\SeaMAC0" 不是有效的命名管道名称。

参考documentation on Pipe Names:

CreateFileWaitNamedPipeCallNamedPipe 函数中指定管道名称时使用以下形式:

\\ServerName\pipe\PipeName

其中ServerName 是远程计算机的名称或句点,用于指定本地计算机。 PipeName 指定的管道名称字符串可以包含除反斜杠以外的任何字符,包括数字和特殊字符。整个管道名称字符串最长可达 256 个字符。管道名称不区分大小写。

管道服务器无法在另一台计算机上创建管道,因此CreateNamedPipe 必须使用句点作为服务器名称,如下例所示。

\\.\pipe\PipeName

因此,在您的第二个“不起作用”示例中,.NET NamedPipeClientStream 将用于连接到服务器管道的构造管道名称是:

\\.\pipe\SeaMAC0

随后在调用WaitNamedPipe Win32 方法时使用它来尝试连接到命名管道服务器,在连接循环中,当调用Connect 时无限超时。鉴于不存在具有给定名称的管道服务器这一事实,它将完全按照您的描述结束:等待,永远孤独。

请注意,对于您使用的文件名 ("\\\\.\\SeaMAC0"):

Win32 Device Namespaces

"\\.\" 前缀将访问 Win32 设备命名空间,而不是 Win32 文件命名空间。

...

如果您使用的是 Windows API 函数,则应使用 "\\.\" 前缀仅访问设备而非文件。

例如\\.\COM1 将打开 COM1 设备的句柄,\\.\DISPLAY1 代表默认显示设备。如果SeaMAC0 不是您系统上的实际设备名称,则您的“工作版本”可能返回一个无效的句柄。如果这样的设备确实存在,它会返回设备的句柄,而不是命名管道实例。

【讨论】:

实际上它是一个设备sealevel.com/store/serial/synchronous-serial/pci-express/… 它是一个同步串行卡。但是感谢您提供的链接,它将让我有机会阅读更多关于此的内容。 @56K 看来这些信息与您的问题非常相关。您可能想要编辑它并添加信息。这也意味着这个答案仍然解释了为什么你会看到你观察到的行为。我会更新答案以纳入您的新信息。

以上是关于从 NamedPipeClientStream 调用命名管道时未连接的主要内容,如果未能解决你的问题,请参考以下文章

NamedPipeServerStream/NamedPipeClientStream 包装器

NamedPipeClientStream - 服务器断开连接时的通知

异步使用 NamedPipeServerStream 和 NamedPipeClientStream

namedpipeclientstream 啥顺序

NamedPipeClientStream 在应用服务中不起作用

关闭 NamedPipeClientStream 时出现 System.Net.Sockets.SocketException