C #: how to set DNS resolution timeout?

I want to check if the host can be resolved, but I do not want to wait long, so I want to set a timeout. I tried

 public static bool ResolveTest(string hostNameOrAddress, int millisecond_time_out)
 {
     var timeoutSpan = TimeSpan.FromMilliseconds(millisecond_time_out);
     var result = Dns.BeginGetHostEntry(hostNameOrAddress, null, null);
     var success = result.AsyncWaitHandle.WaitOne(timeoutSpan);
     if (!success) {
         //throw new Exception("Failed to resolve the domain.");
         return false;
     }
     return true;
 }

but now it works correctly, when it is the wrong host, it can also return true.So, how to set the timeout for DnsResolve?

+4
source share
2 answers

Original answer

see updated answer

There is no way to cancel Dns.BeginGetHostEntry(), but you can try to implement something that can be canceled after a set time. This is a bit hacky, but can do what you requested.

However, DNS queries are usually (usually) very fast and usually resolve in tests within 10 ms.

. Task, Task, bool, .

public static Task<bool> Resolve(string hostNameOrAddress, int millisecond_time_out)
{
    return Task.Run(async () =>
    {
        bool completed = false;
        var asCallBack = new AsyncCallback(ar =>
        {
            ResolveState context = (ResolveState)ar.AsyncState;
            if (context.Result == ResolveType.Pending)
            {
                try
                {
                    var ipList = Dns.EndGetHostEntry(ar);
                    if (ipList == null || ipList.AddressList == null || ipList.AddressList.Length == 0)
                        context.Result = ResolveType.InvalidHost;
                    else
                        context.Result = ResolveType.Completed;
                }
                catch
                {
                    context.Result = ResolveType.InvalidHost;
                }
            }
            completed = true;
        });
        ResolveState ioContext = new ResolveState(hostNameOrAddress);
        var result = Dns.BeginGetHostEntry(ioContext.HostName, asCallBack, ioContext);
        int miliCount = 0;
        while (!completed)
        {
            miliCount++;
            if (miliCount >= millisecond_time_out)
            {
                result.AsyncWaitHandle.Close();
                result = null;
                ioContext.Result = ResolveType.Timeout;
                break;
            }
            await Task.Delay(1);
        }
        Console.WriteLine($"The result of {ioContext.HostName} is {ioContext.Result}");
        return ioContext.Result == ResolveType.Completed;
    });
}

public class ResolveState
{
    public ResolveState(string hostName)
    {
        if (string.IsNullOrWhiteSpace(hostName))
            throw new ArgumentNullException(nameof(hostName));
        _hostName = hostName;
    }

    readonly string _hostName;

    public ResolveType Result { get; set; } = ResolveType.Pending;

    public string HostName => _hostName;

}

public enum ResolveType
{
    Pending,
    Completed,
    InvalidHost,
    Timeout
}

public static async void RunTest()
{
    await Resolve("asdfasdfasdfasdfasdfa.ca", 60);
    await Resolve("google.com", 60);
}

Resolve, AsyncCallBack. Dns.BeginGetHostEntry(). , state ResolveState. . , AsyncCallBack, Result ResolveState. completed .

( , ), , 1ms, , Result Timeout.

, . async, async await.

. , , , . success false, Result WaitOne. , success true ( IP-), , Dns.EndGetHostEntry.

:

public static bool ResolveTest(string hostNameOrAddress, int millisecond_time_out)
{
    ResolveState ioContext = new ResolveState(hostNameOrAddress);
    var result = Dns.BeginGetHostEntry(ioContext.HostName, null, null);
    var success = result.AsyncWaitHandle.WaitOne(TimeSpan.FromMilliseconds(millisecond_time_out), true);
    if (!success)
    {
        ioContext.Result = ResolveType.Timeout;
    }
    else
    {
        try
        {
            var ipList = Dns.EndGetHostEntry(result);
            if (ipList == null || ipList.AddressList == null || ipList.AddressList.Length == 0)
                ioContext.Result = ResolveType.InvalidHost;
            else
                ioContext.Result = ResolveType.Completed;
        }
        catch
        {
            ioContext.Result = ResolveType.InvalidHost;
        }
    }
    Console.WriteLine($"The result of ResolveTest for {ioContext.HostName} is {ioContext.Result}");
    return ioContext.Result == ResolveType.Completed;
}

https://gist.github.com/Nico-VanHaaster/35342c1386de752674d0c37ceaa65e00.

+2

, System.Threading.Tasks.Task.Run() , :

private Task<IPAddress> ResolveAsync(string hostName) {
    return System.Threading.Tasks.Task.Run(() => {
        return System.Net.Dns.GetHostEntry(hostName).AddressList[0];
    });
}

private string ResolveWithTimeout(string hostNameOrIpAddress) {
    var timeout = TimeSpan.FromSeconds(3.0);
    var task = ResolveAsync(hostNameOrIpAddress);
    if (!task.Wait(timeout)) {
        throw new TimeoutException();
    }
    return task.Result.ToString();
}
-1

Source: https://habr.com/ru/post/1651472/


All Articles