检测全局命名空间

时间:2018-04-13 14:19:24

标签: c# wcf synchronization named-pipes

问题:有没有办法快速检查会话0中是否正在托管特定的pipename - 在ServiceHost.Open调用期间是否优先?

情景:

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

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

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

PipeUser 尝试通过 PeacePipe PipeHost 进行通信,它会发送消息,但 PipeHost 不会消息看到了什么。

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

背景

当所选的pipename已经被托管时,

ServiceHost.Open应抛出AddressAlreadyInUseException。

但是,如果管道在会话0中托管并且您尝试在不同的会话中托管相同的管道,则不会抛出它。由于窗口命名管道通常不会在会话中使用。除会话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)中使用命名的互斥锁,以查看是否有其他进程尝试执行相同操作。

然而,即使管道处于2个不同的会话中,这也不合格。

由于我使用多种绑定类型(net.tcp,net.pipe,net.udp)并且拥有用于创建和托管ServiceHost的单一代码,所以ServiceHost.Open会优先考虑这一点。 NamedPipes是唯一可以允许在没有AddressAlreadyInUseException异常的情况下创建新主机的地方,而地址实际上已经在使用中。

0 个答案:

没有答案