From e1a5c360ac09e7950d44d75f6c58b367a5ca385d Mon Sep 17 00:00:00 2001 From: 2dust <31833384+2dust@users.noreply.github.com> Date: Mon, 6 Jul 2026 11:49:54 +0800 Subject: [PATCH] Optimize timeout logic, try fix https://github.com/2dust/v2rayN/issues/9681 --- .../ServiceLib/Handler/ConnectionHandler.cs | 7 ++-- v2rayN/ServiceLib/Helper/DownloaderHelper.cs | 38 +++++++++++-------- v2rayN/ServiceLib/Services/DownloadService.cs | 24 ++++++++---- .../ServiceLib/Services/SpeedtestService.cs | 2 +- 4 files changed, 44 insertions(+), 27 deletions(-) diff --git a/v2rayN/ServiceLib/Handler/ConnectionHandler.cs b/v2rayN/ServiceLib/Handler/ConnectionHandler.cs index a59421e8..80d9d4e7 100644 --- a/v2rayN/ServiceLib/Handler/ConnectionHandler.cs +++ b/v2rayN/ServiceLib/Handler/ConnectionHandler.cs @@ -38,7 +38,7 @@ public static class ConnectionHandler for (var i = 0; i < 2; i++) { - responseTime = await GetRealPingTime(webProxy, 10); + responseTime = await GetRealPingTime(webProxy); if (responseTime > 0) { break; @@ -66,7 +66,7 @@ public static class ConnectionHandler /// /// Measures response time by sending HTTP requests through proxy. /// - public static async Task GetRealPingTime(IWebProxy? webProxy, int downloadTimeout) + public static async Task GetRealPingTime(IWebProxy? webProxy, int downloadTimeout = 9) { var url = AppManager.Instance.Config.SpeedTestItem.SpeedPingTestUrl; var responseTime = -1; @@ -77,7 +77,8 @@ public static class ConnectionHandler using var client = new HttpClient(new SocketsHttpHandler() { Proxy = webProxy, - UseProxy = webProxy != null + UseProxy = webProxy != null, + ConnectTimeout = TimeSpan.FromSeconds(3) }); List oneTime = []; diff --git a/v2rayN/ServiceLib/Helper/DownloaderHelper.cs b/v2rayN/ServiceLib/Helper/DownloaderHelper.cs index 71c3edbe..d65884b0 100644 --- a/v2rayN/ServiceLib/Helper/DownloaderHelper.cs +++ b/v2rayN/ServiceLib/Helper/DownloaderHelper.cs @@ -14,6 +14,8 @@ public class DownloaderHelper return null; } + var connectTimeout = Math.Clamp(timeout / 5, 2, 5); + Uri uri = new(url); //Authorization Header var headers = new WebHeaderCollection(); @@ -27,12 +29,12 @@ public class DownloaderHelper BlockTimeout = timeout * 1000, MaxTryAgainOnFailure = 2, RequestConfiguration = - { - Headers = headers, - UserAgent = userAgent, - ConnectTimeout = timeout * 1000, - Proxy = webProxy - } + { + Headers = headers, + UserAgent = userAgent, + ConnectTimeout = connectTimeout * 1000, + Proxy = webProxy + } }; await using var downloader = new Downloader.DownloadService(downloadOpt); @@ -45,7 +47,9 @@ public class DownloaderHelper }; using var cts = new CancellationTokenSource(); - await using var stream = await downloader.DownloadFileTaskAsync(address: url, cts.Token).WaitAsync(TimeSpan.FromSeconds(timeout), cts.Token); + cts.CancelAfter(TimeSpan.FromSeconds(timeout)); + + await using var stream = await downloader.DownloadFileTaskAsync(address: url, cts.Token); using StreamReader reader = new(stream); downloadOpt = null; @@ -60,15 +64,16 @@ public class DownloaderHelper throw new ArgumentNullException(nameof(url)); } + var connectTimeout = Math.Clamp(timeout / 5, 2, 5); var downloadOpt = new DownloadConfiguration() { BlockTimeout = timeout * 1000, MaxTryAgainOnFailure = 2, RequestConfiguration = - { - ConnectTimeout= timeout * 1000, - Proxy = webProxy - } + { + ConnectTimeout= connectTimeout * 1000, + Proxy = webProxy + } }; var lastUpdateTime = DateTime.Now; @@ -116,7 +121,7 @@ public class DownloaderHelper }; //progress.Report("......"); using var cts = new CancellationTokenSource(); - cts.CancelAfter(timeout * 1000); + cts.CancelAfter(TimeSpan.FromSeconds(timeout)); await using var stream = await downloader.DownloadFileTaskAsync(address: url, cts.Token); downloadOpt = null; @@ -137,15 +142,16 @@ public class DownloaderHelper File.Delete(fileName); } + var connectTimeout = Math.Clamp(timeout / 5, 2, 5); var downloadOpt = new DownloadConfiguration() { BlockTimeout = timeout * 1000, MaxTryAgainOnFailure = 2, RequestConfiguration = - { - ConnectTimeout= timeout * 1000, - Proxy = webProxy - } + { + ConnectTimeout= connectTimeout * 1000, + Proxy = webProxy + } }; var progressPercentage = 0; diff --git a/v2rayN/ServiceLib/Services/DownloadService.cs b/v2rayN/ServiceLib/Services/DownloadService.cs index 1dbdfae2..5db4de7a 100644 --- a/v2rayN/ServiceLib/Services/DownloadService.cs +++ b/v2rayN/ServiceLib/Services/DownloadService.cs @@ -109,9 +109,10 @@ public class DownloadService /// public async Task TryDownloadString(string url, IWebProxy? webProxy, string userAgent) { + var timeout = 15; try { - var result1 = await DownloadStringAsync(url, webProxy, userAgent, 15); + var result1 = await DownloadStringAsync(url, webProxy, userAgent, timeout); if (result1.IsNotEmpty()) { return result1; @@ -129,7 +130,7 @@ public class DownloadService try { - var result2 = await DownloadStringViaDownloader(url, webProxy, userAgent, 15); + var result2 = await DownloadStringViaDownloader(url, webProxy, userAgent, timeout); if (result2.IsNotEmpty()) { return result2; @@ -155,11 +156,18 @@ public class DownloadService { try { - var client = new HttpClient(new SocketsHttpHandler() + var connectTimeout = Math.Clamp(timeout / 5, 2, 5); + var handler = new SocketsHttpHandler { Proxy = webProxy, - UseProxy = webProxy != null - }); + UseProxy = webProxy != null, + ConnectTimeout = TimeSpan.FromSeconds(connectTimeout) + }; + + using var client = new HttpClient(handler) + { + Timeout = Timeout.InfiniteTimeSpan + }; if (userAgent.IsNullOrEmpty()) { @@ -175,8 +183,9 @@ public class DownloadService } using var cts = new CancellationTokenSource(); - var result = await client.GetStringAsync(url, cts.Token).WaitAsync(TimeSpan.FromSeconds(timeout), cts.Token); - return result; + cts.CancelAfter(TimeSpan.FromSeconds(timeout)); + + return await client.GetStringAsync(url, cts.Token); } catch (Exception ex) { @@ -187,6 +196,7 @@ public class DownloadService Error?.Invoke(this, new ErrorEventArgs(ex.InnerException)); } } + return null; } diff --git a/v2rayN/ServiceLib/Services/SpeedtestService.cs b/v2rayN/ServiceLib/Services/SpeedtestService.cs index 1adf3713..44e95fcb 100644 --- a/v2rayN/ServiceLib/Services/SpeedtestService.cs +++ b/v2rayN/ServiceLib/Services/SpeedtestService.cs @@ -420,7 +420,7 @@ public class SpeedtestService(Config config, Func updateF private async Task DoRealPing(ServerTestItem it) { var webProxy = new WebProxy($"socks5://{Global.Loopback}:{it.Port}"); - var responseTime = await ConnectionHandler.GetRealPingTime(webProxy, 10); + var responseTime = await ConnectionHandler.GetRealPingTime(webProxy); ProfileExManager.Instance.SetTestDelay(it.IndexId, responseTime); await UpdateFunc(it.IndexId, responseTime.ToString());