Como (repetidamente) ler no .NET SslStream com um tempo limite?
Eu só preciso ler atéN
bytes de umSslStream
mas se nenhum byte tiver sido recebido antes de um tempo limite, cancele, deixando o fluxo em um estado válido para tentar novamente mais tarde. (*)
Isso pode ser feito facilmente para fluxos não SSL, ou seja,NetworkStream
simplesmente usando seuReadTimeout
propriedade que fará o fluxo lançar uma exceção no tempo limite. Infelizmente, essa abordagem não funcionaSslStream
de acordo com os documentos oficiais:
SslStream supõe que um tempo limite, juntamente com qualquer outra IOException quando um é lançado do fluxo interno, será tratado como fatal pelo chamador. Reutilizar uma instância SslStream após um tempo limite retornará lixo. Um aplicativo deve fechar o SslStream e lançar uma exceção nesses casos.
[Atualizado 1] Eu tentei uma abordagem diferente como esta:
task = stream->ReadAsync(buffer, 0, buffer->Length);
if (task->Wait(timeout_ms)) {
count = task->Result;
...
}
Mas isso não funciona seWait()
devolvidafalse
: ao ligarReadAsync()
novamente mais tarde, lança uma exceção:
Exceção lançada: 'System.NotSupportedException' no System.dll Tests.exe Aviso: 0: Falha na leitura do soquete: System.NotSupportedException: O método BeginRead não pode ser chamado quando outra operação de leitura está pendente.
[Atualização 2] Tentei ainda outra abordagem para implementar tempos limite chamandoPoll(timeout, ...READ)
no subjacenteTcpClient
socket: se retornartrue
, Em seguida, ligueRead()
noSSlStream
ou se retornarfalse
então temos um tempo limite. Isso também não funciona: porqueSslStream
presumivelmente usa seus próprios buffers intermediários internos,Poll()
pode retornarfalse
mesmo se houver dados a serem lidos noSslStream
.
[Atualização 3] Outra possibilidade seria escrever um formulário personalizadoStream
subclasse que ficaria entreNetworkStream
eSslStream
e capture a exceção de tempo limite e retorne 0 bytes paraSslStream
. Não tenho certeza de como fazer isso e, mais importante, não tenho idéia se retornar uma leitura de 0 bytes paraSslStream
ainda não iria corrompê-lo de alguma forma.
(*) A razão pela qual estou tentando fazer isso é que ler de forma síncrona com um tempo limite de um soquete não seguro ou seguro é o padrão que já estou usando no iOS, OS X, Linux e Android para obter código de plataforma cruzada . Como funciona para soquetes não seguros no .NET, o único caso restante éSslStream
.