简体   繁体   English

C# 等待 TcpClient ConnectAsync/ReadToEndAsync 超时

[英]C# await TcpClient ConnectAsync/ReadToEndAsync with timeout

I'm building a SOCKS proxy checker using .NET 4.5 and everything works fine except when one of SOCKS proxies is really slow and it takes over 100 seconds to respond.我正在使用 .NET 4.5 构建一个 SOCKS 代理检查器,并且一切正常,除非其中一个 SOCKS 代理非常慢并且需要超过 100 秒的响应时间。 I'd like to timeout those proxies at few stages (ConnectAsync, ReadToEndAsync) especially at ReadToEndAsync because if proxy is slow it hangs.我想在几个阶段(ConnectAsync,ReadToEndAsync)使这些代理超时,尤其是在 ReadToEndAsync 中,因为如果代理很慢,它就会挂起。

I've tried everything I was able to find about this, using Cancellation tokens, Task.Wait, NetworkStream.ReadTimeout ( doesn't work.. strange ).. and if I use Task.Wait then I can't use await keyword which makes it synchronous and not async and that beats the whole idea of my tool..我已经尝试了我能找到的一切,使用取消标记、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();
                                }
                            }
                        }
                    }
                }

Shamefully, async socket IO does not support timeouts.可耻的是,异步套接字 IO 不支持超时。 You need to build that yourself.你需要自己构建它。 Here is the best approach I know:这是我所知道的最好的方法:

Make your entire function not care about timeouts.让你的整个函数不关心超时。 Disable all of them.禁用所有这些。 Then, start a delay task and when it completes dispose of the socket.然后,启动一个延迟任务,当它完成时处理套接字。 This kills all IO that is in flight and effects immediate cancellation.这会杀死所有正在运行的 IO 并立即取消。

So you could do:所以你可以这样做:

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

This leads to an ugly ObjectDisposedException .这会导致丑陋的ObjectDisposedException This is unavoidable.这是不可避免的。

Probably, you need to cancel the delay in case of success.可能,您需要在成功的情况下取消延迟。 Otherwise you keep a ton of delay tasks for 100 seconds and they might amount to millions depending on load.否则,您将大量延迟任务保留 100 秒,根据负载的不同,它们可能会达到数百万个。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM