17

Hi
I want to use NamedPipeServerStream which is new from .NET 3.5 for namedpipe communication. I want to write multi-threaded pipe server. is it handled by default or I should write code for that. my pipe server should handle multiple request at a time

any solution or code ?

Ehsan
  • 1,662
  • 6
  • 28
  • 49

3 Answers3

28

You can write a multi threaded pipe server by repeatedly creating a NamedPipeServerStream and waiting for one connection, then spawning a thread for that instance of NamedPipeServerStream.

You can only have 254 concurrent clients though according to the .NET MSDN documentation linked below. For Win32 APIs though you can pass a special value to get unlimited based on system resources. It seems the MSDN documentation is wrong as noted below.

The below code is not tested so please do not simply copy and paste for production use without testing:

    public class PipeServer
    {
        bool running;
        Thread runningThread;
        EventWaitHandle terminateHandle = new EventWaitHandle(false, EventResetMode.AutoReset);
        public string PipeName { get; set; }

        void ServerLoop()
        {
            while (running)
            {
                ProcessNextClient();
            }

            terminateHandle.Set();
        }

        public void Run()
        {
            running = true;
            runningThread = new Thread(ServerLoop);
            runningThread.Start();
        }

        public void Stop()
        {
            running = false;
            terminateHandle.WaitOne();
        }

        public virtual string ProcessRequest(string message)
        {
            return "";
        }

        public void ProcessClientThread(object o)
        {
            NamedPipeServerStream pipeStream = (NamedPipeServerStream)o;

            //TODO FOR YOU: Write code for handling pipe client here

            pipeStream.Close();
            pipeStream.Dispose();
        }

        public void ProcessNextClient()
        {
            try
            {
                NamedPipeServerStream pipeStream = new NamedPipeServerStream(PipeName, PipeDirection.InOut, 254);
                pipeStream.WaitForConnection();

                //Spawn a new thread for each request and continue waiting
                Thread t = new Thread(ProcessClientThread);
                t.Start(pipeStream);
            }
            catch (Exception e)
            {//If there are no more avail connections (254 is in use already) then just keep looping until one is avail
            }
        }
Brian R. Bondy
  • 339,232
  • 124
  • 596
  • 636
  • @Brian: Why do you say "you can only have 254 concurrent clients"? By default, NamedPipeServerStream specifies PIPE_UNLIMITED_INSTANCES when calling Win32 CreateNamedPipe API, and Win32 documentation says `the number of pipe instances that can be created is limited only by the availability of system resources`. – Chris Dickson Feb 21 '11 at 10:02
  • `ArgumentOutOfRangeException` is thrown when `maxNumberofServerInstances is less than one or greater than 254. http://msdn.microsoft.com/en-us/library/bb355105.aspx – Brian R. Bondy Feb 21 '11 at 14:09
  • 2
    @Brian: The documentation for the NamedPipeServerStream ctor lies. The value `-1`, corresponding to `PIPE_UNLIMITED_INSTANCES`, is also an acceptable value. `if (((maxNumberOfServerInstances < 1) || (maxNumberOfServerInstances > 0xfe)) && (maxNumberOfServerInstances != -1)) { throw new ArgumentOutOfRangeException("maxNumberOfServerInstances", SR.GetString("ArgumentOutOfRange_MaxNumServerInstances")); } ` – Chris Dickson Feb 22 '11 at 15:55
  • Could you provide another reference that contradicts this documentation I quoted as you mentioned? – Brian R. Bondy Feb 22 '11 at 17:20
  • I see here: http://msdn.microsoft.com/en-us/library/aa365150(v=vs.85).aspx it talks about unlimited based on system resources, but I wonder if the .NET implementation is different? – Brian R. Bondy Feb 22 '11 at 17:21
  • @Chris: I made note of this in my answer. – Brian R. Bondy Feb 22 '11 at 19:50
  • @Brian: The code I quoted in my comment is from the .NET implementation - courtesy of Reflector. -1 is the default value you get if you use one of the ctors which doesn't set maxNumberOfServerInstances. In the code which calls the underlying Win32 API this is translated to PIPE_UNLIMITED_INSTANCES – Chris Dickson Feb 22 '11 at 23:05
  • @Chris: OK cool I updated my answer even more to say that the documentation is wrong. Nice find! – Brian R. Bondy Feb 22 '11 at 23:44
  • FYI. There is a moment when `ProcessClientThread` complited and `pipeStream` was closed, but new `pipeStream` not yet created, and some PipeClient operations will be missed. – dRn Apr 25 '17 at 10:25
23

Each NamedPipeServerStream instance is a Stream implementation wrapping a handle to an instance of a named pipe. You can (and a multithreaded pipe server will) have multiple instances of NamedPipeServerStream for the same named pipe: each one wraps a handle to a different instance of the named pipe, servicing a different client. Named pipe instances (even for the same pipe) are kept separate by the operating system, so there is no need for any explicit coding to keep each client's communication with the server separate.

What you do need to code explicitly is the threading model for the server. The simplest approach to multithreading the server is explained in this SO answer, which includes a pseudo-code template. More scalable implementations, if large numbers of concurrent callers need to be supported, would use thread pooling and the asynchronous methods instead of creating a dedicated thread for each connection.

Community
  • 1
  • 1
Chris Dickson
  • 11,964
  • 1
  • 39
  • 60
0

NamedPipeServerStream is a point to point connection. You have to synchronise the calls yourself - for example calls written to a queue and your server reads from the synchronised queue and makes the calls.

Aliostad
  • 80,612
  • 21
  • 160
  • 208