我只需要从N读取最多SslStream字节,但是如果在超时之前没有收到字节,请取消操作,同时使流保持有效状态,以便稍后重试。 (*)

对于非SSL流,只需使用NetworkStream属性即可轻松完成此操作,即ReadTimeout,这将使流在超时时引发异常。不幸的是,根据官方文档,此方法不适用于SslStream:



[更新1] 我尝试了另一种类似的方法:

task = stream->ReadAsync(buffer, 0, buffer->Length);
if (task->Wait(timeout_ms)) {
   count = task->Result;
   ...
}

但是,如果Wait()返回false,这将不起作用:稍后再次调用ReadAsync()时,它将引发异常:



[更新2] 我尝试了另一种方法来实现超时,方法是在底层Poll(timeout, ...READ)套接字上调用TcpClient:如果它返回true,然后在Read()上调用SSlStream,或者如果它返回false则我们有一个超时。这也不起作用:因为SslStream大概使用了它自己的内部中间缓冲区,即使Poll()中有待读取的数据,false仍可以返回SslStream

[更新3] 另一种可能性是编写一个自定义Stream子类,该子类位于NetworkStreamSslStream之间,并捕获超时异常并返回0个字节,而不是SslStream。我不确定如何执行此操作,更重要的是,我不知道是否将读取到的0字节返回给SslStream仍然不会以某种方式破坏它。

(*)我尝试执行此操作的原因是,从非安全或安全套接字同步读取并超时,这是我已经在iOS,OS X,Linux和Android上针对某些跨平台代码使用的模式。它适用于.NET中的非安全套接字,因此剩下的唯一情况是SslStream

最佳答案

您当然可以使方法1起作用。您只需要跟踪任务并继续等待,而无需再次调用ReadAsync。因此,大致来说:

private Task readTask;     // class level variable
...
  if (readTask == null) readTask = stream->ReadAsync(buffer, 0, buffer->Length);
  if (task->Wait(timeout_ms)) {
     try {
         count = task->Result;
         ...
     }
     finally {
         task = null;
     }
  }

需要充实一点,以便 call 者可以看到读取尚未完成,但是代码段太小,无法给出具体建议。

关于c# - 如何(反复)从.NET SslStream中读取超时?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/37177401/

10-10 01:24