Async two-way communication with Windows Named Pip

2019-01-16 17:11发布

I have a windows service and a GUI that need to communicate with each other. Either can send messages at any time.

I'm looking at using NamedPipes, but it seems that you cant read & write to the stream at the same time (or at least I cant find any examples that cover this case).

Is it possible to do this kind of two-way communication via a single NamedPipe? Or do I need to open two pipes (one from GUI->service and one from service->GUI)?

3条回答
相关推荐>>
2楼-- · 2019-01-16 17:37

Using a single point to accumulate messages (a single pipe in this case) forces you to handle direction of the message yourself too (in addition to that you have to use a system-wide lock for the pipe).

So use 2 pipes with opposite directions.

(Another option would be using 2 MSMQ queues).

查看更多
We Are One
3楼-- · 2019-01-16 17:50

Your named pipe stream classes (server or client) have to be constructed with a PipeDirection of InOut. You need one NamedPipeServerStream, probably in your service, which can be shared by an arbitrary number of NamedPipeClientStream objects. Construct the NamedPipeServerStream with the name of the pipe and the direction, and the NamedPipeClientStream with the name of the pipe, the name of the server, and the PipeDirection, and you should be good to go.

查看更多
淡お忘
4楼-- · 2019-01-16 17:56

Using WCF you can use duplex named pipes

// Create a contract that can be used as a callback
public interface IMyCallbackService
{
    [OperationContract(IsOneWay = true)]
    void NotifyClient();
}

// Define your service contract and specify the callback contract
[ServiceContract(CallbackContract = typeof(IMyCallbackService))]
public interface ISimpleService
{
    [OperationContract]
    string ProcessData();
}

Implement the Service

[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerCall)]
public class SimpleService : ISimpleService
{
    public string ProcessData()
    {
        // Get a handle to the call back channel
        var callback = OperationContext.Current.GetCallbackChannel<IMyCallbackService>();

        callback.NotifyClient();
        return DateTime.Now.ToString();
    }
}

Host the Service

class Server
{
    static void Main(string[] args)
    {
        // Create a service host with an named pipe endpoint
        using (var host = new ServiceHost(typeof(SimpleService), new Uri("net.pipe://localhost")))
        {
            host.AddServiceEndpoint(typeof(ISimpleService), new NetNamedPipeBinding(), "SimpleService");
            host.Open();

            Console.WriteLine("Simple Service Running...");
            Console.ReadLine();

            host.Close();
        }
    }
}

Create the client application, in this example the Client class implements the call back contract.

class Client : IMyCallbackService
{
    static void Main(string[] args)
    {
        new Client().Run();
    }

    public void Run()
    {
        // Consume the service
        var factory = new DuplexChannelFactory<ISimpleService>(new InstanceContext(this), new NetNamedPipeBinding(), new EndpointAddress("net.pipe://localhost/SimpleService"));
        var proxy = factory.CreateChannel();

        Console.WriteLine(proxy.ProcessData());
    }

    public void NotifyClient()
    {
        Console.WriteLine("Notification from Server");
    }
}
查看更多
登录 后发表回答