Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Way to check if NamedPipeServerStream started in Client side

I have a client using NamedPipeClientStream and a server using NamedPipeServerStream.

The client may start before the server, and when it call clientStream.Connect(timeout) i get TimeoutException as expected.

Is there any way I can check if there is a NamedPipeServerStream listening before calling the Connect to prevent an exception?

like image 489
Joseph Avatar asked Aug 06 '15 06:08

Joseph


3 Answers

If someone bumps into this question five years later, this might be helpful:

var isPipeRunning = Directory.GetFiles( @"\\.\pipe\" ).Contains( $"\\.\pipe\{pipeName}" )
like image 156
Csaba Fabian Avatar answered Nov 11 '22 17:11

Csaba Fabian


I suggest you should use an EventWaitHandle. On all clients, call WaitOne () and on server after opening the stream, call Set ().

So, on "server" side, write this:

EventWaitHandle handle = new EventWaitHandle(false, EventResetMode.ManualReset, String.Format(@"Global\{0}", "SERVER_OPENED_HANDLE"));

OpenStream (); // inside this method you would have code that opens your named pipe for incomming messages

// finally, signal that you are done

handle.Set ();

On client side, write something like this:

EventWaitHandle handle = new EventWaitHandle(false, EventResetMode.ManualReset, String.Format(@"Global\{0}", "SERVER_OPENED_HANDLE"));

// here your thread will sleep until the server calls "Set"
handle.WaitOne ();

// then you can safelly connect to the server here

ConnectToServer ();

There remains just a few situations to handle:

1) The pipe can't be opened on server becase there is already an opened pipe with the same name (will throw an exception).

2) You successfully opened the pipe, you notified clients that you are ready but after that, a milisecond after, the server crushes from some unexpected reason and the client cannot reach the server.

3) User rights problems

In all these situations, you should handle these exceptions using a try / catch and normally, if all goes well, this code will ensure that the client will NOT try to connect before the server successfully opened the pipe.

Anyway, I suggest using a more advanced technique for making IPC through Named Pipes such as using WCF or even .NET Remoting wich besides the fact that it's somehow considered obsolete by many (don't include me) is very decent at least for IPC communication. This will give you the freedom and scalability (maybe one day you will need your clients to be able to reside on other machines, and you will have to switch from IPC to a LAN communication or even in WAN / internet).

like image 30
George Lica Avatar answered Nov 11 '22 17:11

George Lica


There is no way to check this only using a NamedPipeClientStream. However, you can use a Mutex like so

// In the server
var mutex = new System.Threading.Mutex(false, "MyPipeMutex");
OpenPipeAndRunServer();
mutex.Close();

// In the client process    
var mutex = new System.Threading.Mutex(false, "MyPipeMutex");
if (!mutex.WaitOne(0, false))
{
    OpenPipe();
}
mutex.Close();

You will probably want to wrap the Close calls in a try-finally block to make sure it always closes. In the client you can use a different timeout to actually wait for the NamedPipe to be opened.

You can also catch the exception as a work around.

like image 2
vidstige Avatar answered Nov 11 '22 17:11

vidstige