diff --git a/FastGithub.Dns/DnsServerHostedService.cs b/FastGithub.Dns/DnsServerHostedService.cs index 773a06b..d4217c2 100644 --- a/FastGithub.Dns/DnsServerHostedService.cs +++ b/FastGithub.Dns/DnsServerHostedService.cs @@ -6,6 +6,8 @@ using System; using System.Diagnostics; using System.Net; using System.Net.Sockets; +using System.Runtime.InteropServices; +using System.Runtime.Versioning; using System.Threading; using System.Threading.Tasks; @@ -17,13 +19,17 @@ namespace FastGithub.Dns sealed class DnsServerHostedService : BackgroundService { private readonly RequestResolver requestResolver; - private readonly IOptions options; + private readonly IOptionsMonitor options; private readonly ILogger logger; private readonly Socket socket = new(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); private readonly byte[] buffer = new byte[ushort.MaxValue]; private IPAddress[]? dnsAddresses; + [SupportedOSPlatform("windows")] + [DllImport("dnsapi.dll", EntryPoint = "DnsFlushResolverCache", SetLastError = true)] + private static extern uint DnsFlushResolverCache(); + /// /// dns后台服务 /// @@ -32,12 +38,24 @@ namespace FastGithub.Dns /// public DnsServerHostedService( RequestResolver requestResolver, - IOptions options, + IOptionsMonitor options, ILogger logger) { this.requestResolver = requestResolver; this.options = options; this.logger = logger; + options.OnChange(opt => FlushResolverCache()); + } + + /// + /// 刷新dns缓存 + /// + private static void FlushResolverCache() + { + if (OperatingSystem.IsWindows()) + { + DnsFlushResolverCache(); + } } /// @@ -45,7 +63,7 @@ namespace FastGithub.Dns /// /// /// - public override Task StartAsync(CancellationToken cancellationToken) + public override async Task StartAsync(CancellationToken cancellationToken) { const int DNS_PORT = 53; if (OperatingSystem.IsWindows() && UdpTable.TryGetOwnerProcessId(DNS_PORT, out var processId)) @@ -53,7 +71,8 @@ namespace FastGithub.Dns Process.GetProcessById(processId).Kill(); } - this.socket.Bind(new IPEndPoint(IPAddress.Any, DNS_PORT)); + await BindAsync(this.socket, new IPEndPoint(IPAddress.Any, DNS_PORT), cancellationToken); + if (OperatingSystem.IsWindows()) { const int SIO_UDP_CONNRESET = unchecked((int)0x9800000C); @@ -61,9 +80,39 @@ namespace FastGithub.Dns } this.logger.LogInformation("dns服务启动成功"); - var secondary = IPAddress.Parse(options.Value.UntrustedDns.IPAddress); + var secondary = IPAddress.Parse(options.CurrentValue.UntrustedDns.IPAddress); this.dnsAddresses = this.SetNameServers(IPAddress.Loopback, secondary); - return base.StartAsync(cancellationToken); + FlushResolverCache(); + + await base.StartAsync(cancellationToken); + } + + /// + /// 尝试多次绑定 + /// + /// + /// + /// + /// + private static async Task BindAsync(Socket socket, IPEndPoint localEndPoint, CancellationToken cancellationToken) + { + var delay = TimeSpan.FromMilliseconds(100d); + for (var i = 10; i >= 0; i--) + { + try + { + socket.Bind(localEndPoint); + break; + } + catch (Exception) + { + if (i == 0) + { + throw; + } + await Task.Delay(delay, cancellationToken); + } + } } ///