Named Pipes Server Timeout

When using C # NamedPipeServerStream in case the client does not send any pattern-end message (for example, \ r \ n when the server is reading using ReadLine ()) Reading methods NamedPipeServerStream will wait forever, and Abort () or Interupt ( ) will work on this thread.

FROM:
1) Stream.ReadTimeout is not supported for NamedPipeServerStream
2) Abort () or Interupt () does not work in the stream
3) NamedPipeServerStream.Disconnect () bottom work
It is unclear how to set the timeout in NamedPipeServerStream read operations.


Let me give you an example. The IPC specification requires the exchange of strings with a null number. The client sends a message, the server processes the message and sends a response as it should. If the client does not send \ 0 at the end (the client is not ours, therefore, we cannot guarantee the correctness of its operation), the Read method will always wait, and the client (since we do not control it) can always wait for an answer too.

The following is a simplified implementation example:

public void RestartServer() { _pipeServerThread.Interrupt(); //doesn't affect Read wait _pipeServerThread.Abort(); //doesn't affect Read wait } private void PipeServerRun(object o) //runs on _pipeServerThread { _pipeServer = new NamedPipeServerStream(_pipeName, InOut, 100, PipeTransmissionMode.Message, PipeOptions.WriteThrough); //_pipeServer.ReadTimeout = 100; //System.InvalidOperationException: Timeouts are not supporte d on this stream. // Wait for a client to connect while (true) { _pipeServer.WaitForConnection(); string request = ReadPipeString(); //... process request, send response and disconnect } } /// <summary> /// Read a \0 terminated string from the pipe /// </summary> private string ReadPipeString() { StringBuilder builder = new StringBuilder(); var streamReader = new StreamReader(_pipeServer); while (true) { //read next byte char[] chars = new char[1]; streamReader.Read(chars, 0, 1); // <- This will wait forever if no \0 and no more data from client if (chars[0] == '\0') return builder.ToString(); builder.Append(chars[0]); } } 

So how to set a timeout for NamedPipeServerStream read operations?

+7
source share
2 answers

Since you start the channel in message mode, you must first read the entire message in the byte[] buffer or in the memory stream, and then decide whether it really decrypts it. The pipe posts have a specific length. It cannot be obtained explicitly, but it is displayed when you read from the message channel. Win32 ReadFile fails with ERROR_MORE_DATA if the message still has unread bytes, then it returns TRUE to indicate that the message has completed. After that, the ReadFile call will be blocked until a new message appears. StreamReader naturally does not know about this and blocks your stream.

Update: To execute timeouts, use asynchronous I / O ( Stream.BeginRead ). StreamReader does not support this directly. If you absolutely must use it, write a wrapper thread that will implement Read in terms of BeginRead in the underlying thread and support timeouts, undo, etc.

+2
source

Try setting NamedPipeServerStream.ReadMode and / or .TransmissionMode to Byte. Regardless, you should use the available BeginRead / EndRead methods with NamedPipeServerStream. This way you can implement the timeout logic yourself.

+1
source

All Articles