Skip to content

Services Over Named Pipes

tylerje edited this page Oct 23, 2014 · 1 revision

From MSDN

A named pipe is a named, one-way or duplex pipe for communication between the pipe server and one or more pipe clients. All instances of a named pipe share the same pipe name, but each instance has its own buffers and handles, and provides a separate conduit for client/server communication. The use of instances enables multiple pipe clients to use the same named pipe simultaneously. Any process can access named pipes, subject to security checks, making named pipes an easy form of communication between related or unrelated processes. Any process can act as both a server and a client, making peer-to-peer communication possible. As used here, the term pipe server refers to a process that creates a named pipe, and the term pipe client refers to a process that connects to an instance of a named pipe.

Using Named Pipes across the network requires UDP and/or TCP communication under the covers. But using Named Pipes on the same machine occurs in memory via the operation system and is incredibly fast. For process to process communication on the same machine, we highly recommend that you use Named Pipes.

Your use of Named Pipes with ServiceWire

Here's the code you would write to use create, host and use a service over Named Pipes.

In a shared assemly--your interface and data contracts

 public interface IMyTester
 {
    Guid GetId(string source, double weight, int quantity);
    TestResponse Get(Guid id, string label, double weight, out int quantity);
    List<string> GetItems(Guid id, int[] vals);
 }
 
 [Serializable]
 public struct TestResponse
 {
    public Guid Id { get; set; }
    public string Label { get; set; }
    public long Quantity { get; set; }
 }

On the server--your interface implementation and hosting

 public class MyTester : IMyTester
 {
    private string longLabel = string.Empty;
    private const int totalKilobytes = 140;
    private Random rand = new Random(DateTime.Now.Millisecond);
 
    public MyTester()
    {
       var sb = new StringBuilder();
       for (int i = 0; i < totalKilobytes; i++)
       {
          for (int k = 0; k < 1024; k++) sb.Append(((char)rand.Next(32, 126)));
       }
       longLabel = sb.ToString();
    }
 
 
    public Guid GetId(string source, double weight, int quantity)
    {
       return Guid.NewGuid();
    }
 
    public TestResponse Get(Guid id, string label, double weight, out int quantity)
    {
       quantity = 44;
       return new TestResponse { Id = id, Label = longLabel, Quantity = quantity };
    }
 
    public List<string> GetItems(Guid id, int[] vals)
    {
       var list = new List<string>();
       list.Add("42");
       list.Add(id.ToString());
       list.Add("MyTest");
       list.Add(longLabel);
       return list;
    }
 }
 
 static void Main(string[] args)
 {
    // logger and stats are optional 
    // there is a null implementation by default
    var logger = new Logger(logLevel: LogLevel.Debug);
    var stats = new Stats();
 
    var pipeName = "ServiceWireTestHost";
 
    var mytester = new MyTester();
 
    var nphost = new NpHost(pipeName, logger, stats);
    nphost.AddService<IMyTester>(mytester);
 
    nphost.Open();
 
    Console.WriteLine("Press Enter to stop the dual host test.");
    Console.ReadLine();
 
    nphost.Close();
 
    Console.WriteLine("Press Enter to quit.");
    Console.ReadLine();
 }

On the client--easy

 private static void Main(string[] args)
 {
    var pipeName = "ServiceWireTestHost";
 
    using (var client = new NpClient<IMyTester>(new NpEndPoint(pipeName)))
    {
       for (int i = 0; i < 10; i++)
       {
             var id = client.Proxy.GetId("test1", 3.314, 42);
             int q2 = 4;
             var response = client.Proxy.Get(id, "mirror", 4.123, out q2);
             var list = client.Proxy.GetItems(id, new int[] { 3, 6, 9 });
       }
    }
    
    Console.ReadLine();
 }
And that's all there is to it.