Мне просто нужно прочитать до N
байт от SslStream
, но если байт не был получен до истечения таймаута, отмените его, оставив поток в допустимом состоянии, чтобы повторить попытку позже. (*)Как (неоднократно) читать с .NET 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: Ошибка чтения m socket: System.NotSupportedException: метод BeginRead не может быть вызван при ожидании другой операции чтения.
[Update 2] Я попробовал еще один подход к реализации таймаута по телефону Poll(timeout, ...READ)
на подстилающей TcpClient
сокета: если она возвращает true
, а затем вызвать Read()
на SSlStream
, или если она возвращает false
то мы имеем тайм-аут. Это также не работает: потому что SslStream
предположительно использует свои собственные внутренние промежуточные буферы, Poll()
может возвращать false
, даже если в есть данные.
[Update 3] Другой возможностью было бы написать собственный Stream
подкласс, который будет сидеть между NetworkStream
и SslStream
и захватить исключение тайм-аут и возвращает 0 байт, вместо того, чтобы SslStream
. Я не уверен, как это сделать, и, что более важно, я понятия не имею, что возвращение 0 байтов, прочитанных в SslStream
, все равно не испортило бы его.
(*) Причина, по которой я пытаюсь сделать это, заключается в том, что чтение синхронно с тайм-аутом из незащищенного или защищенного сокета - это шаблон, который я уже использую в iOS, OS X, Linux и Android для некоторых межплатформенный код. Он работает для незащищенных сокетов в .NET, поэтому единственным оставшимся случаем является SslStream
.
Родственный вопрос здесь: http://stackoverflow.com/questions/24198290/net-4-5-sslstream-cancel-a-asynchronous-read-write-call – Pol