J'ai juste besoin de lire jusqu'à N
octets à partir d'un SslStream
mais si aucun octet n'a été reçu avant un délai, annuler, tout en laissant le flux dans un état valide afin d'essayer à nouveau plus tard. (*)Comment lire (à plusieurs reprises) à partir de .NET SslStream avec un délai d'expiration?
Cela peut être fait facilement pour les flux non-SSL, c'est-à-dire NetworkStream
, simplement en utilisant sa propriété ReadTimeout
qui fera que le flux lancera une exception au délai d'attente. Malheureusement, cette approche ne fonctionne pas sur SslStream
par les documents officiels:
SslStream suppose qu'un délai d'attente ainsi que tout autre IOException quand on est éjecté du flux interne sera traitée comme fatale par son appelant. Réutiliser une instance de SslStream après un délai d'expiration retournera la poubelle. Une application doit fermer le SslStream et lancer une exception dans ces cas.
[Mise à jour 1] J'ai essayé une approche différente comme ceci:
task = stream->ReadAsync(buffer, 0, buffer->Length);
if (task->Wait(timeout_ms)) {
count = task->Result;
...
}
Mais cela ne fonctionne pas si Wait()
retourné false
: lorsque vous appelez ReadAsync()
plus tard, il lance une exception:
Exception levée: 'System.NotSupportedException' dans System.dll Tests.exe Avertissement: 0: Lecture impossible à partir de s ocket: System.NotSupportedException: La méthode BeginRead ne peut pas être appelée lorsqu'une autre opération de lecture est en attente.
[Mise à jour 2] J'ai essayé une autre approche pour mettre en œuvre les délais d'attente en appelant Poll(timeout, ...READ)
sur la prise TcpClient
sous-jacente: si elle retourne true
, puis appelez Read()
sur le SSlStream
, ou si elle retourne false
alors nous avons un temps libre. Cela ne fonctionne pas non plus: parce que SslStream
utilise vraisemblablement ses propres tampons intermédiaires internes, Poll()
peut renvoyer false
même s'il reste des données à lire dans le SslStream
.
[Mise à jour 3] Une autre possibilité serait d'écrire une sous-classe personnalisée Stream
qui siègerait entre NetworkStream
et SslStream
et capturer l'exception de délai d'attente et retour 0 octets au lieu de SslStream
. Je ne suis pas sûr de savoir comment faire cela, et plus important encore, je ne sais pas si retourner 0 octets lus à SslStream
ne serait toujours pas le corrompre en quelque sorte.
(*) La raison pour laquelle j'essaye de faire ceci est que la lecture synchrone avec un délai d'une prise non-sûre ou sûre est le modèle que j'utilise déjà sur iOS, OS X, Linux et Android pour code multiplateforme. Il fonctionne pour les sockets non sécurisés dans .NET, le seul cas restant est SslStream
.
Une question connexe ici: http://stackoverflow.com/questions/24198290/net-4-5-sslstream-cancel-a-asynchronous-read-write-call – Pol