locked
NamedPipes read\write RRS feed

  • Question

  • I need to create two threads one for reading and one for writing. I tried to do this with two NamedPipeClientStreams but the second thread faild to Connect. After that I tried to work with one NamedPipeClientStream for both threads but in this case the Read method was blocked and that cause the Write to hang.

    Is this concept is right or I missing something with NamedPipes?

    How should it be done?

    Tuesday, June 26, 2012 8:00 PM

Answers

  • It sounds like you have some misconceptions about the way named pipes work. The bottom line is that you have to use a duplex pipe, and if the server is already working and writing messages both ways as you suggest, then that is what the server is expecting. The long explanation is below.

    First, in your first paragraph you suggest that you can't use a duplex pipe because you don't know when messages will be received from the server. You can still use a duplex pipe, and in fact you typically have to, even if you don't know when messages will be coming in and out. You would want to make the pipe asynchronous also (see PipeOptions). Then you can use the BeginRead method with the IAsyncResult pattern to process messages from the server whenever they occur.

    Relating to changing the server code, assuming it is written in native C++, the server must have created the named pipe using the CreateNamedPipe function, which requires the pipe direction to be specified. If the server is already sending messages both ways, it means that it must already be set to PIPE_ACCESS_DUPLEX, which is the native equivalent of PipeDirection.InOut. In other words, the server is already written to support a duplex pipe scenario.

    On your proposed design of having two different clients, it will not actually work. The server can only connect to one client at a time on a named pipe - it's impossible to accept a second client without dropping the first (which is why you're being blocked). The named pipe server will only accept connections when the ConnectNamedPipe function is called. When that's called, your first client is allowed to connect, and the client and server can communicate. When your second client tries to connect, it is blocked until the server calls ConnectNamedPipe again to accept a second client. If you look at the linked documentation, you'll see that ConnectNamedPipe will not work if there is already a client connected to the pipe. You have to either use a newly created pipe, or you have to call DisconnectNamedPipe to drop the previous client before a new one can be connected. The end result is that your two clients can't both be connected to the server at the same time.


    Check out My Blog. Now updated to actually work!

    Thursday, June 28, 2012 4:40 PM
  • Yep, you're correct. If you use BeginRead, you can wait for a message to occur and write messages at the same time.

    Check out My Blog. Now updated to actually work!

    Thursday, June 28, 2012 6:24 PM
  • Hi OhadR,

      NamedPipClientStreams is the client endpoints when using named-pipe client for IPC. The full name of IPC is inter-process communication.It seems that you can read this code sample to getting the more information.

      C# named-pipe client for IPC (CSNamedPipeClient) 

      C# named-pipe server for IPC (CSNamedPipeServer) 

      Hope it helps you.

      Sincerely,

      Jason Wang

     


    Jason Wang [MSFT]
    MSDN Community Support | Feedback to us

    Wednesday, June 27, 2012 8:46 AM
  • You don't necessarily have to have a read thread. You can have a duplex pipe, which allows the client to write messages to the server and the server to write messages back to the client. You need to use one of the overloads of the NamedPipeServerStream and NamedPipeClientStream constructors which takes a PipeDirection, and pass in PipeDirection.InOut. Once you have the pipe established, you can read and write messages on both ends without needing a second client thread.


    Check out My Blog. Now updated to actually work!

    Wednesday, June 27, 2012 6:59 PM

All replies

  • I'm not sure I'm following your exact use case. I'm sure there are ways to do what you'd like to do, but I'm not sure exactly what that is yet.

    If I understand correctly, you have two threads running in the same application. From both threads, you need to connect to a named pipe. Where is the other end of the named pipe? Is the server end of the pipe running somewhere else, or are you just trying to communicate between the two threads?

    I'm guessing you have a service running somewhere that is listening to the pipe. You create two NamedPipeClientStream objects on the client, but the second one fails to connect. What happens when it fails to connect? Do you get a specific exception?


    Check out My Blog. Now updated to actually work!

    Tuesday, June 26, 2012 8:20 PM
  • Hi OhadR,

      NamedPipClientStreams is the client endpoints when using named-pipe client for IPC. The full name of IPC is inter-process communication.It seems that you can read this code sample to getting the more information.

      C# named-pipe client for IPC (CSNamedPipeClient) 

      C# named-pipe server for IPC (CSNamedPipeServer) 

      Hope it helps you.

      Sincerely,

      Jason Wang

     


    Jason Wang [MSFT]
    MSDN Community Support | Feedback to us

    Wednesday, June 27, 2012 8:46 AM
  • Yes, the two client threads are running in the same application on the client side. The server runs on a different process and listens to requests. In addition, the server can also send some informative messages to the clients and for that I need to have a read thread on the client side as well. About the exact exception I will check it tomorrow.

    Thanks for your reply.

    Ohad.

    Wednesday, June 27, 2012 6:19 PM
  • You don't necessarily have to have a read thread. You can have a duplex pipe, which allows the client to write messages to the server and the server to write messages back to the client. You need to use one of the overloads of the NamedPipeServerStream and NamedPipeClientStream constructors which takes a PipeDirection, and pass in PipeDirection.InOut. Once you have the pipe established, you can read and write messages on both ends without needing a second client thread.


    Check out My Blog. Now updated to actually work!

    Wednesday, June 27, 2012 6:59 PM
  • Your suggestion is a good idea when you have a known protocol (like when the client asks a request and the server answers this request), but in my case the server can also send some independent messages to the client and the client from his side waits for incoming request that should be sent to the server.

    Actuly the design I have is a given one, because the server is already written (in c++) and it works fine. What I need to do is to rewrite only the client in c# (if I could rewrite also the server I could use two pipes one for reading and one for writing, but I can not change the server and as I was told this design (implements in c++) works fine for several years.

    You also asked me "What happens when it fails to connect? Do you get a specific exception?" - I don't get an exception but the second thread can not Connect and it stays blocked in the Connect.


    Thanks agian.

    Thursday, June 28, 2012 3:57 PM
  • It sounds like you have some misconceptions about the way named pipes work. The bottom line is that you have to use a duplex pipe, and if the server is already working and writing messages both ways as you suggest, then that is what the server is expecting. The long explanation is below.

    First, in your first paragraph you suggest that you can't use a duplex pipe because you don't know when messages will be received from the server. You can still use a duplex pipe, and in fact you typically have to, even if you don't know when messages will be coming in and out. You would want to make the pipe asynchronous also (see PipeOptions). Then you can use the BeginRead method with the IAsyncResult pattern to process messages from the server whenever they occur.

    Relating to changing the server code, assuming it is written in native C++, the server must have created the named pipe using the CreateNamedPipe function, which requires the pipe direction to be specified. If the server is already sending messages both ways, it means that it must already be set to PIPE_ACCESS_DUPLEX, which is the native equivalent of PipeDirection.InOut. In other words, the server is already written to support a duplex pipe scenario.

    On your proposed design of having two different clients, it will not actually work. The server can only connect to one client at a time on a named pipe - it's impossible to accept a second client without dropping the first (which is why you're being blocked). The named pipe server will only accept connections when the ConnectNamedPipe function is called. When that's called, your first client is allowed to connect, and the client and server can communicate. When your second client tries to connect, it is blocked until the server calls ConnectNamedPipe again to accept a second client. If you look at the linked documentation, you'll see that ConnectNamedPipe will not work if there is already a client connected to the pipe. You have to either use a newly created pipe, or you have to call DisconnectNamedPipe to drop the previous client before a new one can be connected. The end result is that your two clients can't both be connected to the server at the same time.


    Check out My Blog. Now updated to actually work!

    Thursday, June 28, 2012 4:40 PM
  • Thank you for your quick reply.

    Does working asynchronously (with beginRean and callback) mean that I can wait for reading asynchronously and in the same time write messages to the server?

    I'll check this option (about working asynchronously) instead of using another thread.

    (In the changing of the server design I ment that the server application can have two NamedPipes in two different threads, one for reading and one for writing).

    Thanks alot,

    Ohad.

    Thursday, June 28, 2012 6:05 PM
  • Yep, you're correct. If you use BeginRead, you can wait for a message to occur and write messages at the same time.

    Check out My Blog. Now updated to actually work!

    Thursday, June 28, 2012 6:24 PM
  • Thanks!!! It works !!!
    Thursday, June 28, 2012 8:16 PM
  • Glad it's working! Let us know if any other issues come up.

    Check out My Blog. Now updated to actually work!

    Thursday, June 28, 2012 8:32 PM