1
votes

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();                
 }
3
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
@GeorgeKerwood. This is false. According to the documentation are Named Pipes for one or more pipe clients: docs.microsoft.com/en-us/dotnet/api/…. - Iliass Nassibane
@Lliass Nassibane. Agreed, the remarks are misleading against the following: docs.microsoft.com/en-us/windows/win32/ipc/…. Perhaps this is helpful: codeproject.com/Articles/864679/… - George Kerwood

3 Answers

0
votes

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
votes

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;
         }
     }
}