Время ожидания чтения сервера именованных каналов

при использовании C# NamedPipeServerStream, в случае, если клиент не отправляет никаких сообщений-end-pattern (например, rn, когда сервер читает с помощью ReadLine()) NamedPipeServerStream методы чтения будут ждать вечно, и никакие методы Abort() или Interupt() не будут работать в этом потоке.

С:
1) поток.ReadTimeout не поддерживается для NamedPipeServerStream
2) Abort () или Interupt () не работает в потоке
3) NamedPipeServerStream.Disconnect () nether work
Неясно, как настроить тайм-аут для операций чтения NamedPipeServerStream?


позвольте мне привести пример. Спецификация МПК мы требовать обмен -завершенные строки. Клиент отправляет сообщение, сервер обрабатывает сообщение и как 'должен' отправляет ответ. Если клиент не отправляет в конце (клиент не наш, поэтому мы не можем гарантировать правильность его работы), метод чтения будет ждать вечно, и клиент (поскольку мы его не контролируем) может ждать вечно ответ тоже.

далее приведен упрощенный пример реализации:

    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?

2 ответов


поскольку вы запускаете канал в режиме сообщения, Вы должны сначала прочитать все сообщение в byte[] буфер или поток памяти и затем решите, является ли он действительным и декодировать его. Сообщения канала имеют определенную длину. Его нельзя получить явно, но он отображается при чтении из канала режима сообщения. С Win32 ReadFile выдает ERROR_MORE_DATA Если в сообщении все еще есть непрочитанные байты, то он возвращает TRUE, чтобы указать, что сообщение закончилось. После этот вызов ReadFile будет блокировать, пока новое сообщение не будет доступно. StreamReader естественно, не знает ничего из этого и блокирует ваш поток.

обновление: для реализации таймаутов используйте асинхронный ввод-вывод (Stream.BeginRead). StreamReader не поддерживает это напрямую. Если вы абсолютно должны использовать его, напишите поток обертки, который будет реализовывать Read С точки зрения BeginRead на базовом потоке и таймаутах поддержки, отмене и т. д.


попробуйте установить NamedPipeServerStream.ReadMode and / or .TransmissionMode в байт. Независимо от этого вы должны использовать доступные методы BeginRead / EndRead с NamedPipeServerStream. Таким образом, вы можете реализовать логику таймаут себя.