【问题标题】:Two unique named pipes conflicting and InvalidCredentialException两个唯一的命名管道冲突和 InvalidCredentialException
【发布时间】:2023-11-05 11:55:01
【问题描述】:

我昨晚遇到了两个问题,现在我已经解决了,但我不能 100% 确定为什么我所做的事情已经解决了这些问题,并希望有人能在我转向时提供一些见解翻过很多石头,运气不好!

第一个问题

第一个问题是我有两个唯一命名的管道,它们位于两个单独的程序中:

  • net.pipe://localhost/superuniquepipe1
  • net.pipe://localhost/superuniquepipe2

但是,由于地址已在使用中,第二个启动的程序在打开 ServiceHost 时会抛出异常(我相信是 AddressAlreadyInUseException)。

实例化这些 ServiceHost 的方式如下:

Uri[] baseAddresses = new Uri[] { new Uri("net.pipe://localhost") };
this.host = new ServiceHost(this, baseAddresses);
this.host.AddServiceEndpoint(typeof(IHostType), new NetNamedPipeBinding(), "superuniquepipe1");
this.host.Open();

所以我会先指定localhost的基地址,然后在添加端点时指定其余部分,我解决这个问题的方法是更改​​代码如下:

this.host = new ServiceHost(this);
this.host.AddServiceEndpoint(typeof(IHostType), new NetNamedPipeBinding(), "net.pipe://localhost/superuniquepipe2");
this.host.Open();

我是否正确地说这有效的原因是因为它只检查基地址而不是我试图添加的端点?并且使用第二个代码示例是让多个程序在“localhost”上侦听的有效/安全方式吗?

第二个问题

为了解决上述问题,我将基地址从 localhost 更改为许多不同的唯一字符串,例如“net.pipe://rawrwhyisntthisworkingsadface”,但在执行此操作时,我会收到来自尝试建立连接的客户端的 InvalidCredentialException(请参见下面的代码)

我的印象是命名管道实际上可以命名任何东西,有人能解释一下吗?

ChannelFactory<IHostType> factory = new ChannelFactory<IHostType>(new NetNamedPipeBinding(), new EndpointAddress("net.pipe://rawrwhyisntthisworkingsadface/superuniquepipe2"));
IHostType proxy = factory.CreateChannel();
proxy.CallSomeMethodAndGetAnException();

任何意见将不胜感激,正如我所说,我已经解决了这个问题,只是想知道为什么我的解决方案有效,但是如果您发现我解决问题的方式存在缺陷,并且可以提出更好的解决方法请这样做:)

【问题讨论】:

  • 为了扩展这一点,我遇到了同样的问题,我相信这是一个例外:[TYPE]: System.ServiceModel.AddressAlreadyInUseException [MESSAGE ]: 无法侦听管道名称“net.pipe://localhost/”,因为另一个管道端点已经在侦听该名称。

标签: c# wcf remoting named-pipes


【解决方案1】:

关于问题1:

WCF NetNamedPipeBinding 使用命名的共享内存部分向其客户端发布可以调用服务的管道的实际名称。管道名称本身是一个 GUID,每次打开服务主机时都会重新生成。它是用于发布依赖于服务 URL 的服务的共享内存部分的名称。如果定义了基地址,则基地址用于派生该名称。

这意味着您一次只能运行一个 WCF 服务应用程序,该应用程序使用特定的基地址作为其 NetNamedPipe 端点。如果您尝试启动第二个,则会失败并显示 AddressAlreadyInUseException,因为它发现 WCF 想要用于发布位置的名称(从基地址派生)已被另一个应用程序占用。

如果您不指定基地址,并为每个服务提供一个绝对的、唯一的服务 URL,那么发布位置的名称现在是从完整的绝对 URL 派生的,并且应用程序之间没有名称冲突。这是让多个 WCF 命名管道服务侦听的完全有效且安全的方法。

关于问题2:

在服务端,您可以使用任何内容作为服务 URL 的主机名部分。这是因为在 NetNamePipeBinding 中默认应用了 HostNameComparisonMode 设置,因为 WCF 中为共享内存发布位置派生名称的算法用通配符替换主机名 see here 以启用配置的主机名比较模式待实施。

然而,在客户端,服务 URL 受到限制:主机部分必须真正解析为 localhost(即它是 localhost、正确的 IP 地址或正确的机器名称)。

【讨论】:

  • 感谢您提供的所有信息,非常感谢 :)
最近更新 更多