Search code examples
c#httpwebrequestdotnet-httpclient

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).


Solution

  • 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.