Ho solo bisogno di leggere fino a N
byte da un SslStream
ma se nessun byte è stato ricevuto prima di un timeout, annullare, lasciando il flusso in uno stato valido per riprovare più tardi. (*)Come leggere (ripetutamente) da .NET SslStream con un timeout?
Questo può essere fatto facilmente per flussi non SSL, ad esempio NetworkStream
, semplicemente utilizzando la proprietà ReadTimeout
che farà sì che il flusso generi un'eccezione sul timeout. Purtroppo questo approccio non funziona su SslStream
per la documentazione ufficiale:
SslStream presuppone che un timeout insieme a qualsiasi altra IOException quando si è gettato dal flusso interno sarà trattato come fatale per il suo chiamante. Riutilizzare un'istanza SslStream dopo un timeout restituirà garbage. Un'applicazione dovrebbe chiudere lo SslStream e generare un'eccezione in questi casi.
[Aggiornamento 1] ho provato un approccio diverso come questo:
task = stream->ReadAsync(buffer, 0, buffer->Length);
if (task->Wait(timeout_ms)) {
count = task->Result;
...
}
Ma questo non funziona se Wait()
restituito false
: al momento della chiamata ReadAsync()
più tardi viene generata un'eccezione:
Eccezione generata: "System.NotSupportedException" in System.dll Tests.exe Avviso: 0: lettura non riuscita da s ocket: System.NotSupportedException: il metodo BeginRead non può essere chiamato quando è in attesa un'altra operazione di lettura.
[Update 2] ho provato ancora un altro approccio per implementare timeout chiamando Poll(timeout, ...READ)
sul sottostante TcpClient
presa: se restituisce true
, quindi chiamare Read()
sul SSlStream
, o se restituisce false
poi abbiamo una tempo scaduto. Anche questo non funziona: poiché SslStream
utilizza presumibilmente i propri buffer di intermediazione interni, Poll()
può restituire false
anche se i dati restano da leggere nello SslStream
.
[Update 3] Un'altra possibilità sarebbe quella di scrivere un Stream
sottoclasse personalizzata che si sedeva tra il NetworkStream
e SslStream
e catturare l'eccezione di timeout e restituire 0 byte invece SslStream
. Non sono sicuro di come farlo e, cosa più importante, non ho idea se restituire 0 byte letti a SslStream
non lo danneggerebbe in qualche modo.
(*) La ragione per cui sto provando a fare questo è che leggere in sincronia con un timeout da un socket non sicuro o sicuro è lo schema che sto già usando su iOS, OS X, Linux e Android per alcuni codice multipiattaforma. Funziona con socket non protetti in .NET, quindi l'unico caso rimanente è SslStream
.
Una questione collegata qui: http://stackoverflow.com/questions/24198290/net-4-5-sslstream-cancel-a-asynchronous-read-write-call – Pol