using FastGithub.Configuration; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; using System.Text.Json; using System.Threading; using System.Threading.Tasks; namespace FastGithub.DomainResolve { /// /// 域名的IP测速服务 /// sealed class DomainSpeedTester { private const string DOMAINS_JSON_FILE = "domains.json"; private readonly DnsClient dnsClient; private readonly ILogger logger; private readonly object syncRoot = new(); private readonly Dictionary domainIPAddressHashSet = new(); /// /// 域名的IP测速服务 /// /// /// public DomainSpeedTester( DnsClient dnsClient, ILogger logger) { this.dnsClient = dnsClient; this.logger = logger; try { this.LoadDomains(); } catch (Exception ex) { logger.LogWarning($"加载域名数据失败:{ex.Message}"); } } /// /// 加载域名数据 /// private void LoadDomains() { if (File.Exists(DOMAINS_JSON_FILE) == false) { return; } var utf8Json = File.ReadAllBytes(DOMAINS_JSON_FILE); var domains = JsonSerializer.Deserialize(utf8Json); if (domains == null) { return; } foreach (var domain in domains) { this.domainIPAddressHashSet.TryAdd(domain, new IPAddressItemHashSet()); } } /// /// 添加要测速的域名 /// /// public void Add(string domain) { lock (this.syncRoot) { if (this.domainIPAddressHashSet.TryAdd(domain, new IPAddressItemHashSet())) { try { this.SaveDomains(); } catch (Exception ex) { logger.LogWarning($"保存域名数据失败:{ex.Message}"); } } } } /// /// 保存域名 /// private void SaveDomains() { var domains = this.domainIPAddressHashSet.Keys .Select(item => new DomainPattern(item)) .OrderBy(item => item) .Select(item => item.ToString()) .ToArray(); var utf8Json = JsonSerializer.SerializeToUtf8Bytes(domains, new JsonSerializerOptions { WriteIndented = true }); File.WriteAllBytes(DOMAINS_JSON_FILE, utf8Json); } /// /// 获取测试后排序的IP /// /// /// public IPAddress[] GetIPAddresses(string domain) { lock (this.syncRoot) { if (this.domainIPAddressHashSet.TryGetValue(domain, out var hashSet) && hashSet.Count > 0) { return hashSet.ToArray().OrderBy(item => item.PingElapsed).Select(item => item.Address).ToArray(); } return Array.Empty(); } } /// /// 进行一轮IP测速 /// /// /// public async Task TestSpeedAsync(CancellationToken cancellationToken) { KeyValuePair[] keyValues; lock (this.syncRoot) { keyValues = this.domainIPAddressHashSet.ToArray(); } foreach (var keyValue in keyValues) { var domain = keyValue.Key; var hashSet = keyValue.Value; await foreach (var address in this.dnsClient.ResolveAsync(domain, cancellationToken)) { hashSet.Add(new IPAddressItem(address)); } await hashSet.PingAllAsync(); } } } }