HttpWebRequest's Timeout and ReadWriteTimeout

2020-05-21 08:58发布

问题:

I believe I understand the practical differences between HttpWebRequest.Timeout and HttpWebRequest.ReadWriteTimeout. However, I'm seeking further clarity on the difference between these two timeouts, including what these values mean with respect to the underlying TCP connection/buffers/state if applicable.

For instance, are these timeouts used only during the initialization of the TCP connection, or are these only managed values for keeping watch on the unmanaged connection?

What are the client-server scenarios in TCP terms where each of these timeouts would apply or not apply?

回答1:

This problem has been debated on another question, see Adjusting HttpWebRequest Connection Timeout in C#. The discussion made my head spin, so I'll offer my summary.

Although, MSDN explains that the HttpWebRequest.Timeout Property applies to HttpWebRequest.GetResponse and HttpWebRequest.GetRequestStream calls, the description is a bit confusing.

Jim Mischel is more helpful: Timeout "is the time for the server to respond to a request, not the amount of time to wait for the server to respond and send down all of the data." Thus, Timeout covers establishing a working connection. For large payloads, this does not imply that the request/reply is complete.

ReadWriteTimeout applies to Read or Write operations to streams that transmit over the connection. E.g. when you Write to the stream returned by GetRequestStream. The connection is already established, but there is a risk that it will break. E.g. the network connection goes down.

The Jim Mischel link has some very good advice on what values to set these timeout. I.e. the default for ReadWriteTimeout is too long.



回答2:

I believe you got the first part of your answer from @Donal Lafferty. Here's a quick summary anyway.

HttpWebRequest.Timeout - The time before which the server has to accept the client's request. Note that this doesn't include the DNS resolution time, which is managed by the ServicePointManager.

HttpWebRequest.ReadWriteTimeout - The time before which the client has to receive the entire body of the response from the server. Note that this timeout starts only after the server accepts the request.

The answer to your second question is two-folded.

1. Synchronous request:

The TCP connections are closed on timeout, everybody's happy.

2. Asynchronous request:

These timeouts have absolutely no effect. If you do not have an appropriate mechanism for handing the time-outs, the TCP connections will stay open.

That's precisely the reason why you Abort the request by registering a timeout on the AsyncWaitHandle, as shown in the example here:

http://msdn.microsoft.com/library/21k58ta7.aspx



回答3:

.Timeout = time spent trying to establish a connection (not including lookup time) .ReadWriteTimeout = time spent trying to read or write data after connection established



回答4:

The previous answers suggest changing the ReadWriteTimeout and the timeout. Here's the Webclient override function you need to do this.

        protected override WebRequest GetWebRequest(Uri address)
        {
            _request = base.GetWebRequest(address);

            var httpRequest = _request as HttpWebRequest;
            httpRequest.ReadWriteTimeout = 600000;
            httpRequest.Timeout = 600000;
            httpRequest.ContinueTimeout = 600000;
            if (_request != null)
            {
                httpRequest.AllowAutoRedirect = AutoRedirect;
                httpRequest.CookieContainer = CookieContainer;
                httpRequest.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;

                Setup?.Invoke(httpRequest);
            }

            return _request;
        }