【问题标题】:C# await TcpClient ConnectAsync/ReadToEndAsync with timeoutC# 等待 TcpClient ConnectAsync/ReadToEndAsync 超时
【发布时间】:2015-12-08 21:38:42
【问题描述】:

我正在使用 .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();
                                }
                            }
                        }
                    }
                }

【问题讨论】:

    标签: c# asynchronous tcpclient


    【解决方案1】:

    遗憾的是,异步套接字 IO 不支持超时。您需要自己构建它。这是我所知道的最好的方法:

    让你的整个函数不关心超时。禁用所有这些。然后,启动一个延迟任务,并在它完成时处理套接字。这会杀死所有正在运行的 IO 并立即取消。

    所以你可以这样做:

    Task.Delay(TimeSpan.FromSeconds(100)).ContinueWith(_ => socksTcpClient.Dispose());
    

    这导致了一个丑陋的ObjectDisposedException。这是不可避免的。

    如果成功,您可能需要取消延迟。否则,您会在 100 秒内保留大量延迟任务,根据负载情况,它们可能会达到数百万。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-10-04
      • 2020-09-29
      • 1970-01-01
      • 1970-01-01
      • 2012-04-19
      • 2012-09-20
      • 1970-01-01
      相关资源
      最近更新 更多