Время ожидания чтения сервера именованных каналов
при использовании 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. Таким образом, вы можете реализовать логику таймаут себя.