Как (неоднократно) читать из .NET SslStream с таймаутом?
Мне просто нужно прочитать доN
байты изSslStream
но если байт не был получен до истечения времени ожидания, отмените его, оставив поток в допустимом состоянии, чтобы повторить попытку позже. (*)
Это может быть легко сделано для потоков без SSL, т.е.NetworkStream
просто используя егоReadTimeout
свойство, которое заставит поток вызвать исключение по таймауту. К сожалению, этот подход не работает наSslStream
согласно официальным документам:
SslStream предполагает, что таймаут вместе с любым другим IOException, когда он выбрасывается из внутреннего потока, будет вызываться вызывающим как фатальный. Повторное использование экземпляра SslStream после истечения времени ожидания вернет мусор. Приложение должно закрыть SslStream и выдать исключение в этих случаях.
[Обновлено 1] Я попробовал другой подход, как это:
task = stream->ReadAsync(buffer, 0, buffer->Length);
if (task->Wait(timeout_ms)) {
count = task->Result;
...
}
Но это не работает, еслиWait()
возвращенныйfalse
: при звонкеReadAsync()
позже снова выдает исключение:
Возникло исключение: «System.NotSupportedException» в System.dll Tests.exe Предупреждение: 0: сбой чтения из сокета: System.NotSupportedException: метод BeginRead не может быть вызван, когда другая операция чтения ожидает выполнения.
[Обновление 2] Я попробовал еще один подход для реализации таймаутов, позвонивPoll(timeout, ...READ)
на основеTcpClient
сокет: если он возвращаетtrue
затем позвонитеRead()
наSSlStream
или если он вернетсяfalse
тогда у нас есть тайм-аут. Это тоже не работает: потому чтоSslStream
предположительно использует свои собственные внутренние промежуточные буферы,Poll()
может вернутьсяfalse
даже если есть данные для чтения вSslStream
.
[Обновление 3] Другой возможностью было бы написать кастомStream
подкласс, который будет сидеть междуNetworkStream
а такжеSslStream
и захватить исключение тайм-аута и вернуть 0 байтов вместоSslStream
, Я не уверен, как это сделать, и что более важно, я понятия не имею, возвращаю ли 0 байтов, прочитанныхSslStream
все равно не испортишь это как-то.
(*) Причина, по которой я пытаюсь это сделать, заключается в том, что синхронное чтение с тайм-аутом из незащищенного или безопасного сокета - это шаблон, который я уже использую в iOS, OS X, Linux и Android для некоторого кроссплатформенного кода. , Это работает для небезопасных сокетов в .NET, поэтому единственный оставшийся случайSslStream
.