From 2bc292483bbe2b5e42b9b4403e10b3c6f17402bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=80=81=E4=B9=9D?= <366193849@qq.com> Date: Fri, 19 Nov 2021 23:39:23 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84IP=E6=B5=8B=E9=80=9F=E7=BC=93?= =?UTF-8?q?=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FastGithub.DomainResolve/DomainResolver.cs | 8 +-- .../IPAddressStatusService.cs | 53 ++++++++++--------- 2 files changed, 29 insertions(+), 32 deletions(-) diff --git a/FastGithub.DomainResolve/DomainResolver.cs b/FastGithub.DomainResolve/DomainResolver.cs index 9d245e2..816d0b1 100644 --- a/FastGithub.DomainResolve/DomainResolver.cs +++ b/FastGithub.DomainResolve/DomainResolver.cs @@ -109,13 +109,7 @@ namespace FastGithub.DomainResolve hashSet.Add(address); } - var statusArray = await this.statusService.GetParallelAsync(hashSet, dnsEndPoint.Port, cancellationToken); - var newAddresses = statusArray - .Where(item => item.Elapsed < TimeSpan.MaxValue) - .OrderBy(item => item.Elapsed) - .Select(item => item.Address) - .ToArray(); - + var newAddresses = await this.statusService.GetAvailableAddressesAsync(hashSet, dnsEndPoint.Port, cancellationToken); if (oldAddresses.SequenceEqual(newAddresses) == false) { this.dnsEndPointAddress[dnsEndPoint] = newAddresses; diff --git a/FastGithub.DomainResolve/IPAddressStatusService.cs b/FastGithub.DomainResolve/IPAddressStatusService.cs index 73c62bb..0ebb56f 100644 --- a/FastGithub.DomainResolve/IPAddressStatusService.cs +++ b/FastGithub.DomainResolve/IPAddressStatusService.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Net; +using System.Net.NetworkInformation; using System.Net.Sockets; using System.Threading; using System.Threading.Tasks; @@ -13,30 +14,40 @@ namespace FastGithub.DomainResolve { /// /// IP状态服务 - /// 连接成功的IP缓存5分钟 - /// 连接失败的IP缓存2分钟 + /// 状态缓存5分钟 + /// 连接超时5秒 /// sealed class IPAddressStatusService { - private readonly TimeSpan activeTTL = TimeSpan.FromMinutes(5d); - private readonly TimeSpan negativeTTL = TimeSpan.FromMinutes(2d); + private readonly TimeSpan brokeExpiration = TimeSpan.FromMinutes(1d); + private readonly TimeSpan normalExpiration = TimeSpan.FromMinutes(5d); private readonly TimeSpan connectTimeout = TimeSpan.FromSeconds(5d); private readonly IMemoryCache statusCache = new MemoryCache(Options.Create(new MemoryCacheOptions())); - /// - /// 并行获取多个IP的状态 + /// 并行获取可连接的IP /// /// /// /// /// - public Task GetParallelAsync(IEnumerable addresses, int port, CancellationToken cancellationToken) + public async Task GetAvailableAddressesAsync(IEnumerable addresses, int port, CancellationToken cancellationToken) { - var statusTasks = addresses.Select(item => this.GetAsync(item, port, cancellationToken)); - return Task.WhenAll(statusTasks); + if (addresses.Any() == false) + { + return Array.Empty(); + } + + var statusTasks = addresses.Select(item => this.GetStatusAsync(item, port, cancellationToken)); + var statusArray = await Task.WhenAll(statusTasks); + return statusArray + .Where(item => item.Elapsed < TimeSpan.MaxValue) + .OrderBy(item => item.Elapsed) + .Select(item => item.Address) + .ToArray(); } + /// /// 获取IP状态 /// @@ -44,7 +55,7 @@ namespace FastGithub.DomainResolve /// /// /// - public async Task GetAsync(IPAddress address, int port, CancellationToken cancellationToken) + private async Task GetStatusAsync(IPAddress address, int port, CancellationToken cancellationToken) { var endPoint = new IPEndPoint(address, port); if (this.statusCache.TryGetValue(endPoint, out var status)) @@ -52,19 +63,6 @@ namespace FastGithub.DomainResolve return status; } - status = await this.GetAddressStatusAsync(endPoint, cancellationToken); - var ttl = status.Elapsed < TimeSpan.MaxValue ? this.activeTTL : this.negativeTTL; - return this.statusCache.Set(endPoint, status, ttl); - } - - /// - /// 获取IP状态 - /// - /// - /// - /// - private async Task GetAddressStatusAsync(IPEndPoint endPoint, CancellationToken cancellationToken) - { var stopWatch = Stopwatch.StartNew(); try { @@ -72,12 +70,17 @@ namespace FastGithub.DomainResolve using var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeoutTokenSource.Token); using var socket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); await socket.ConnectAsync(endPoint, linkedTokenSource.Token); - return new IPAddressStatus(endPoint.Address, stopWatch.Elapsed); + + status = new IPAddressStatus(endPoint.Address, stopWatch.Elapsed); + return this.statusCache.Set(endPoint, status, this.normalExpiration); } catch (Exception) { cancellationToken.ThrowIfCancellationRequested(); - return new IPAddressStatus(endPoint.Address, TimeSpan.MaxValue); + + status = new IPAddressStatus(endPoint.Address, TimeSpan.MaxValue); + var expiration = NetworkInterface.GetIsNetworkAvailable() ? this.normalExpiration : this.brokeExpiration; + return this.statusCache.Set(endPoint, status, expiration); } finally {