我正在使用.NET 4.5构建SOCKS代理检查程序,一切正常,除非其中一个SOCKS代理非常慢并且需要超过100秒才能响应。我想在几个阶段(ConnectAsync,ReadToEndAsync)超时这些代理,特别是在ReadToEndAsync,因为如果代理很慢,它会挂起。
我已经尝试了一切我能找到的,使用取消令牌,Task.Wait,NetworkStream.ReadTimeout(不起作用..奇怪).. 如果我使用Task.Wait然后我不能使用await关键字,这使得它同步而不是异步,并且击败了我的工具的整个想法..
var socksClient = new Socks5ProxyClient(IP,Port);
var googleAddress = await Dns.GetHostAddressesAsync("google.com");
var speedStopwatch = Stopwatch.StartNew();
using(var socksTcpClient = await socksClient.CreateConnection(googleAddress[0].ToString(),80))
{
if(socksTcpClient.Connected)
{
using(var socksTcpStream = socksTcpClient.GetStream())
{
socksTcpStream.ReadTimeout = 5000;
socksTcpStream.WriteTimeout = 5000; //these don't work..
using (var writer = new StreamWriter(socksTcpStream))
{
await writer.WriteAsync("GET / HTTP/1.1\r\nHost: google.com\r\n\r\n");
await writer.FlushAsync();
using (var reader = new StreamReader(socksTcpStream))
{
var result = await reader.ReadToEndAsync(); // up to 250 seconds hang on thread that is checking current proxy..
reader.Close();
writer.Close();
socksTcpStream.Close();
}
}
}
}
}
答案 0 :(得分:2)
可耻的是,异步套接字IO不支持超时。你需要自己构建它。这是我所知道的最佳方法:
让你的整个功能不关心超时。禁用所有这些。然后,启动延迟任务,并在完成插槽的处理时。这会杀死所有正在飞行的IO并立即取消。
所以你可以这样做:
Task.Delay(TimeSpan.FromSeconds(100)).ContinueWith(_ => socksTcpClient.Dispose());
这会导致丑陋的ObjectDisposedException
。这是不可避免的。
可能需要在成功的情况下取消延迟。否则你会在100秒内完成大量延迟任务,根据负载情况,这些任务可能达到数百万。