命名管道服务器读取超时

当使用C#NamedPipeServerStream时,如果客户端不发送任何消息结束模式(例如服务器使用ReadLine()读取时的 r n),NamedPipeServerStream读取方法将永远等待,并且不会有Abort()或Interupt()方法在该线程上工作。

以来:
1)Stream.ReadTimeout不受NamedPipeServerStream支持
2)Abort()或Interupt()在线程上不起作用
3)NamedPipeServerStream.Disconnect()可以工作
目前还不清楚,如何在NamedPipeServerStream读取操作上设置超时?


我来介绍一个例子。 IPC的规范我们要求交换 0终止的字符串。 客户端发送消息,服务器处理消息并且'必须'发送响应。 如果客户端最终没有发送 0(客户端不是我们的,所以我们不能保证其工作的正确性),Read方法将永远等待并且客户端(因为我们不控制它)可能永远等待也是一个回应。

接下来是一个实现的简化示例:

    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  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  and no more data from client

            if (chars[0] == '') return builder.ToString();
            builder.Append(chars[0]);
        }
    }

那么如何在NamedPipeServerStream读取操作上设置超时?


由于您在消息模式下运行管道,因此应先将整个消息读取到一个byte[]缓冲区或内存流中,然后确定它是否有效并将其解码。 管道消息具有确定的长度。 它不能被明确地检索,但是当你从消息模式管道读取时它会显示出来。 如果消息中仍有未读字节,则Win32 ReadFile将以ERROR_MORE_DATA失败,然后返回TRUE以指示消息已结束。 在此之后,对ReadFile的调用将会阻塞,直到有新消息可用。 StreamReader自然不知道这些,并阻止你的线程。

更新:实现超时,使用异步I / O( Stream.BeginRead )。 StreamReader不直接支持这一点。 如果您绝对必须使用它,请编写一个包装流,它将在基础流上实现ReadBeginRead方面,并支持超时,取消等。


尝试将NamedPipeServerStream.ReadMode和/或.TransmissionMode设置为Byte。 无论如何,您应该将可用的BeginRead / EndRead方法与NamedPipeServerStream一起使用。 这样你可以自己实现超时逻辑。

链接地址: http://www.djcxy.com/p/8459.html

上一篇: Named pipes server read timeout

下一篇: Determine if an application is blocked/busy?