using DNS.Client; using DNS.Client.RequestResolver; using DNS.Protocol; using DNS.Protocol.ResourceRecords; using System; using System.Linq; using System.Net; using System.Threading; using System.Threading.Tasks; namespace FastGithub.DomainResolve { /// /// DNS客户端 /// sealed class DnsClient { private readonly IPEndPoint dns; private readonly IRequestResolver resolver; private readonly TimeSpan timeout = TimeSpan.FromSeconds(5d); /// /// DNS客户端 /// /// public DnsClient(IPEndPoint dns) { this.dns = dns; this.resolver = dns.Port == 53 ? new TcpRequestResolver(dns) : new UdpRequestResolver(dns, new TcpRequestResolver(dns)); } /// /// 解析域名 /// /// /// /// public async Task LookupAsync(string domain, CancellationToken cancellationToken = default) { var request = new Request { RecursionDesired = true, OperationCode = OperationCode.Query }; request.Questions.Add(new Question(new Domain(domain), RecordType.A)); var clientRequest = new ClientRequest(this.resolver, request); using var timeoutTokenSource = new CancellationTokenSource(this.timeout); using var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeoutTokenSource.Token); var response = await clientRequest.Resolve(linkedTokenSource.Token); return response.AnswerRecords.OfType().Select(item => item.IPAddress).ToArray(); } /// /// 转换为文本 /// /// public override string ToString() { return $"dns://{this.dns}"; } } }