检测全局命名空间中具有相同名称的管道服务器

问题描述 投票:0回答:1

问题: 有没有办法快速检查特定管道名称是否托管在会话 0 中 - 最好是在 ServiceHost.Open 调用期间?

场景:

两个进程 PipeHostPipeUser 正在尝试通过名称为 PeacePipe 的管道在系统上进行通信。它们不需要以特殊权限启动。

PipeHost 已启动并托管 PeacePipe,没有任何问题。

PipeUser 已启动并连接到 PeacePipe,没有任何问题。

PipeUser 尝试通过 PeacePipePipeHost 进行通信,它发送消息,但 PipeHost 看不到任何内容。

事实上 PipeUser 连接到 DifferentPipeHostInSession0,它在提升的(或服务)进程中托管具有相同名称的管道(但操作系统创建不同的管道)。

背景:

当选定的管道名已被托管时,

ServiceHost.Open应该抛出AddressAlreadyInUseException。

但是,如果管道托管在会话 0 中并且您尝试在不同会话中托管相同的管道,则不会抛出此错误。由于 Windows 命名管道通常不能跨会话使用。除了会话 0 中托管的管道之外。任何进程都可以连接到此类管道。这可能会导致上述情况。

代码:

    [ServiceContract]
    public interface IService
    {
        [OperationContract]
        void Ping();
    }

    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple, IncludeExceptionDetailInFaults = true)]
    public class Service: IService
    {
        public void Ping()
        {
            Console.WriteLine("Client Pinged me");
        }
    }

    private static readonly Uri _pipeUri = new Uri("net.pipe://localhost/aaa");
    private static readonly Binding _pipeBinding = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None);

    static void PipeHostTest()
    {
        ServiceHost serviceHost = new ServiceHost(new Service(), _pipeUri);
        serviceHost.AddServiceEndpoint(typeof(IService), _pipeBinding, "");

        try
        {
            //Fail here if same pipe already opened - even in Global space
            serviceHost.Open();
            Console.WriteLine("OPENED");
        }
        catch (AddressAlreadyInUseException e)
        {
            Console.WriteLine(e);
            throw;
        }

        Console.ReadKey();
    }

    static void PipeClient()
    {
        ChannelFactory<IService> channelFactory = 
            new ChannelFactory<IService>(_pipeBinding, new EndpointAddress(_pipeUri));
        var proxy = channelFactory.CreateChannel();

        proxy.Ping();
    }


    static void Main(string[] args)
    {
        if (args.Any())
        {
            PipeClient();
        }
        else
        {
            PipeHostTest();
        }
    }

在不提升参数的情况下运行一次,在不提升参数的情况下运行一次。两个进程都将托管具有相同名称的管道 - 但它们是不同的管道。 然后使用任意参数运行一次。客户端进程将连接到提升进程托管的管道。

可能的解决方案: 在全局会话中使用命名互斥体

new Mutex(true, "Global\\MutexForMyPipeName", out createdNew)
来查看是否有另一个进程尝试执行相同的操作。

然而,即使管道位于两个不冲突的不同会话中,这也会取消资格。

最好是 ServiceHost.Open 会为我处理这个问题,因为我使用多种绑定类型(net.tcp、net.pipe、net.udp)并且具有用于创建和托管 ServiceHost 的单个代码。 NamedPipes 是唯一可以允许创建新主机而不会出现 AddressAlreadyInUseException 异常的管道,而地址实际上已在使用中。

c# wcf synchronization named-pipes
1个回答
0
投票

管道不像其他内核对象那样具有命名空间。
同一管道的多个服务器是一个“功能”,请参阅 CreateNamedPipe

nMaxInstances

另请参阅https://stackoverflow.com/a/7572877/5647513

© www.soinside.com 2019 - 2024. All rights reserved.