我只需要从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
子类,该子类位于NetworkStream
和SslStream
之间,并捕获超时异常并返回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/