两个唯一的命名管道冲突和InvalidCredentialException

时间:2012-04-28 09:27:05

标签: c# wcf remoting named-pipes

我昨晚遇到了两个问题,我现在已经解决了,但我不能100%确定为什么我所做的已经解决了这些问题,希望也许有人可以提供一些见解,因为我一直在转在很多岩石上,没有运气!

第一个问题

第一个问题是我在两个独立的程序中有两个唯一命名的管道:

  • net.pipe://本地主机/ superuniquepipe1
  • net.pipe://本地主机/ superuniquepipe2

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

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

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();

任何输入都会非常感激,因为我说我已经解决了这个问题并且只是想知道为什么我的解决方案有效,但是如果你看到我如何解决它的一个缺陷并且可以建议一个更好的方法来做到这一点请这样做:))

1 个答案:

答案 0 :(得分:14)

问题1:

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

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

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

问题2:

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

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