Morten Mertner Morten Mertner - 1 month ago 15
C# Question

How can I specify a connection-only timeout when executing web requests?

I'm currently using code that makes HTTP requests using the HttpClient class. Although you can specify a timeout for the request, the value applies to the entirety of the request (which includes resolving the host name, establishing a connection, sending the request and receiving the response).

I need a way to make requests fail fast if they cannot resolve the name or establish a connection, but I also sometimes need to receive large amounts of data, so cannot just reduce the timeout.

Is there a way to achieve this using either a built in (BCL) class or an alternative HTTP client stack?

I've looked briefly at RestSharp and ServiceStack, but neither seems to provide a timeout just for the connection part (but do correct me if I am wrong).

Answer

You can use a Timer to abort the request if the connection take too much time. Add an event when the time is elapsed. You can use something like this:

static WebRequest request;
private static void sendAndReceive()
{
    // The request with a big timeout for receiving large amout of data
    request = HttpWebRequest.Create("http://localhost:8081/index/");
    request.Timeout = 100000;

    // The connection timeout
    var ConnectionTimeoutTime = 100;
    Timer timer = new Timer(ConnectionTimeoutTime);
    timer.Elapsed += connectionTimeout;
    timer.Enabled = true;

    Console.WriteLine("Connecting...");
    try
    {
        using (var stream = request.GetRequestStream())
        {
            Console.WriteLine("Connection success !");
            timer.Enabled = false;

            /*
             *  Sending data ...
             */
            System.Threading.Thread.Sleep(1000000);
        }

        using (var response = (HttpWebResponse)request.GetResponse())
        {
            /*
             *  Receiving datas...
             */
        }
    }
    catch (WebException e)
    {
        if(e.Status==WebExceptionStatus.RequestCanceled) 
            Console.WriteLine("Connection canceled (timeout)");
        else if(e.Status==WebExceptionStatus.ConnectFailure)
            Console.WriteLine("Can't connect to server");
        else if(e.Status==WebExceptionStatus.Timeout)
            Console.WriteLine("Timeout");
        else
            Console.WriteLine("Error");
    }
}

static void connectionTimeout(object sender, System.Timers.ElapsedEventArgs e)
{
    Console.WriteLine("Connection failed...");
    Timer timer = (Timer)sender;
    timer.Enabled = false;

    request.Abort();
}

Times here are just for example, you have to adjust them to your needs.