2

I'm creating a windows service that would communicate with another application. The problem I'm facing is that the NamedPipeServerStream closes as soon as the client disconnects. I want that the server should remain open, so whenever the client application starts, it gets connected.

I don't want to use WCF, the messages would be small, so I just want to keep it simple using Named Pipes. Multiple clients can connect to the service. Is there a way to keep the server always running?

This is what I have so far:

 var server = new NamedPipeServerStream("pipeeee123");
 server.SetAccessControl(pipeSa);
 server.WaitForConnection();

 StreamReader reader = new StreamReader(server);
 StreamWriter writer = new StreamWriter(server);
 while (true)
 {
     var line = reader.ReadLine();

     this.EventLog.WriteEntry("Got command " + line, EventLogEntryType.Information);
     var resp = HandleCommand(line);
     writer.WriteLine(resp);
     writer.Flush();                
 }
Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
mrid
  • 5,782
  • 5
  • 28
  • 71
  • My understanding of pipes this that they are inherently for one to one connections, that terminate on disconnect. "Multiple clients can connect to the services"... sounds like you'd be better with the TCPListener/TCPClient classes on localhost? – George Kerwood May 16 '20 at 08:14
  • @GeorgeKerwood. This is false. According to the documentation are Named Pipes for one or more pipe clients: https://learn.microsoft.com/en-us/dotnet/api/system.io.pipes.namedpipeserverstream?view=netcore-3.1. – Iliass Nassibane May 16 '20 at 08:17
  • @Lliass Nassibane. Agreed, the remarks are misleading against the following: https://learn.microsoft.com/en-us/windows/win32/ipc/named-pipe-instances?redirectedfrom=MSDN. Perhaps this is helpful: https://www.codeproject.com/Articles/864679/Creating-a-Server-Using-Named-Pipes – George Kerwood May 16 '20 at 08:41

3 Answers3

2

Take a look at this code.

var server = new NamedPipeServerStream("PipesOfPiece");
StreamReader reader = new StreamReader(server);
StreamWriter writer = new StreamWriter(server);
while (true)
{
    if (!server.IsConnected)
    {
        try
        {
            server.WaitForConnection();
        }
        catch (IOException)
        {
            server.Disconnect();
            continue;
        }
    }

    var line = reader.ReadLine();
    if (!server.IsConnected)
    {
        continue;
    }

    if(!string.IsNullOrEmpty(line))
    {
         writer.WriteLine(String.Join("", line.Reverse()));
    }
    writer.Flush();
}

From what I see, your server just falls because you don't correctly process reopening of connnection + edge cases. Also, consider the fact that you can only work with once instance of a client at a time.

0

Named Pipe Instances are expected to terminate on client disconnect, see: https://learn.microsoft.com/en-us/windows/win32/ipc/named-pipe-instances?redirectedfrom=MSDN.

For multiple clients services, see the following project: https://www.codeproject.com/Articles/864679/Creating-a-Server-Using-Named-Pipes

Also perhaps helpful: How to use named pipes in C# correctly -- several connections, server recreation etc

George Kerwood
  • 1,248
  • 8
  • 19
0

I know it's not asynchronous, but if anybody wants a synchronous version, I was able to get it working using the following:

NamedPipeServerStream server = new NamedPipeServerStream("pipeee", 
    PipeDirection.InOut, 10,
    PipeTransmissionMode.Message, 
    PipeOptions.WriteThrough, 1024, 1024, pipeSecurity);

while (true)
{
     // re-connect if disconnected
     if (!server.IsConnected)
     {
          server = new NamedPipeServerStream("pipeee", 
              PipeDirection.InOut, 10,
              PipeTransmissionMode.Message, 
              PipeOptions.WriteThrough, 1024, 1024, pipeSecurity);
     }

     server.WaitForConnection();

     StreamReader reader = new StreamReader(server);
     StreamWriter writer = new StreamWriter(server);
     while (true)
     {
         var line = reader.ReadLine();

         var resp = HandleCommand(line);
         writer.WriteLine(resp);
         writer.Flush();

         // exit inner loop if disconnected, outer loop will handle re connection
         if(!server.IsConnected)
         {
             break;
         }
     }
}
mrid
  • 5,782
  • 5
  • 28
  • 71