Subject: Of HTTP/1.1 persistent connections and TCP Keepalive timers

From: [email-masked]
Date: Wed, 01 Nov 2000 23:43:48 -0800

I'm curious about how HTTP/1.1 [RFC2616] persistent connections typically work 
with respect to the typical browsers out in the wild today (Netscape & 
Microsoft being the two I'm particularly interested in). If I cause a browser 
to send a GET request for a given URL (using HTTP/1.1) to a server, and the 
server doesn't encounter any errors in processing it and responding, and then 
I (say) don't touch the browser for hours, what *typically* happens to the 
established HTTP/1.1 (-over-TCP) connection?

I note that RFC2616 says (in part)..

                             :
8 Connections

8.1 Persistent Connections
                             :
   HTTP implementations SHOULD implement persistent connections.
                             :
   A significant difference between HTTP/1.1 and earlier versions of
   HTTP is that persistent connections are the default behavior of any
   HTTP connection. That is, unless otherwise indicated, the client
   SHOULD assume that the server will maintain a persistent connection,
   even after error responses from the server.
                             :

As it is written, this effectively puts the responsibility for closing the 
HTTP/1.1-cum-TCP connection on the client.

In nosing around on this subject, I note that in [W.R.Stevens, TCP/IP 
Illustrated Vol 1, http://www.dqc.org/~chris/tcpip_ill/], in chapter 23 
Stevens says that..

1. "Keepalives are not part of the TCP specification. ... Nevertheless, many 
implementations provide the keep-alive timer."

2. "If there is no activity on a given connection for 2 hours, the server 
sends a probe segment to the client. ... A perpetual question by people 
discovering the keepalive option is whether the 2-hour idle time value can be 
changed. They normally want it much lower, on the order of minutes. As we show 
in Appendix E, the value can usually be changed, but in all the systems 
described in this appendix, the keepalive interval is a system-wide value, so 
changing it affects all users of the option. "

..and in appendix E he shows kernel configuration parameters for several 
Unix-based TCP implementations, most all of which have a default 2-hour 
timeout *before* a keepalive packet will be sent.

I also note that Microsoft shows a default value of 2 hour idletime for the 
keepalive timer in this doc:

  http://www.microsoft.com/technet/winnt/reskit/sur_tcp2.asp

Some questions (again, in the case of HTTP/1.1 persistent connections):

Q1. Do the popular browsers typically take the platform's OS's TCP defaults 
for
the keepalive (if such capability is provided by the TCP/IP stack, and if it 
is actually used by the browser), or do they typically set this value to 
something in particular?

Q2. What typical assumptions are made on the browsers' parts about an 
established connection to a web site in the absence of user actions? If a
browser opened a HTTP/1.1 connection and the server is behaving as-specified 
by RFC2616, then it is up to the browser to close the connection. What do 
browsers typically do? I looked through the documented configuration 
parameters for Netscape Communicator..

  http://docs.iplanet.com/docs/manuals/communicator/newprefs/newprefn.html

..and could not find a timeout setting that's applicable for this particular 
case. How long will browsers, that are speaking HTTP/1.1, let this connection 
sit in the ESTABLISHED state?

Q3. Are the popular browsers typically using HTTP/1.1, or HTTP/1.0? I didn't 
notice any config parameters that might have something to do with setting the 
default.

thanks,

JeffH

---

From: "Joris Dobbelsteen" <[email-masked]>
Date: Thu, 2 Nov 2000 16:24:23 +0100

> -----Original Message-----
> From: [email-masked]
> [mailto:[email-masked]]On Behalf Of
> [email-masked]
> Sent: Thursday, 02 November 2000 8:44
> To: [email-masked]
> Cc: [email-masked]
> Subject: Of HTTP/1.1 persistent connections and TCP Keepalive timers
> 
> 

<<<SNIP>>>

> is actually used by the browser), or do they typically set 

HTTP/1.1 does not rely on the TCP timeout/keepalive. A HTTP/1.1 connected is alive only if the lower-layer connection is in the CONNECTED state.
> sit in the ESTABLISHED state?

The browser can leave the connection open for an infinite ammount of time (if not restricted by lower-level protocols, like TCP).

However, idle time-outs when the connection is CONNECTED are, in the real world, handled by the server instead of the client. This is because the server is not interrested in HTTP connections that are idle for an infinite ammount of time and just consuming bandwidth (the lower-level connection must be maintained)...

In the real world, the server does close the connection (when it's idle) without an explicit message that the connection is going to be closed. The server also cannot do this on HTTP level.

> notice any config parameters that might have something to do with setting the 

HTTP/1.1, this version indicates the browser is capable of handling features that are not supported in HTTP/1.0 (such as HTTP keepalive).

MSIE (for Windows) supports HTTP/1.1, but also HTTP/1.0 (default for proxy connections). Here the settings can be changed...

The version is also always send with a HTTP request or response (to indicate the browser/server capacties).

> JeffH

Hope to inform you. Maybe comments from the WG?

- Joris

---

From: James Lacey <[email-masked]>
Date: Thu, 02 Nov 2000 09:26:01 -0600

> established HTTP/1.1 (-over-TCP) connection?

The web server will close the connection due to inactivity.

You have to realize that web servers are trying to service literally
thousands of clients with only a relatively few TCP/IP connections.
If you don't use it you lose it.

Also, most web servers actively look for reasons to close a connection
to a client. For example, if the web server generates any dynamic content
for the client, then it will usually close the connection after the response it
sent back. Regardless of whether or not the client supplied a Connection:
Keep-Alive header or not. The reasoning behind this is that if the sever
had to generate dynamic content on your behalf, then you've had your share
and its time to give some other poor slob a turn.

> HTTP/1.1-cum-TCP connection on the client.

Nope. See my comments above.

Also, you have to realize that just cuz  the client sends a
Connection: Keep-Alive header it is in no way a guarantee
that the server will not close the connection after the
response is sent back.

There is a HUGE difference between the way the HTTP spec
is written and the way that web server's are actually designed
to work on the internet.

I'm not saying that the web server designers violated the
HTTP protocol. Rather they have simply done what they
have to do in order to protect their web server from
attacks, deadlocks, and starving clients.

Read further in the spec and you will see that the HTTP
spec says that unsafe methods should not be pipelined.

An unsafe method is a method that in some sense changes
the state of the server and will not necessarily generate the
same response every time it is executed.

On the internet unsafe methods are typically used to
represent a clients actions on the internet (i.e. I've just
sent a request to buy product X with my credit card
number aaaa-bbbb-cccc-dddd). Before submitting
another unsafe method I should be allowed to get
feedback about the current unsafe method and determine
if I wish to proceed with the next unsafe method or not.
So, when receiving an unsafe method (POST) most
web servers will close the connection after the response
is generated. Even if more unsafe methods have been sent
into the pipe. They are simply discarded.

>   http://www.microsoft.com/technet/winnt/reskit/sur_tcp2.asp

Here I think you are confusing TCP/IP keep alive, with HTTP's
Connection header and its Keep-Alive value.

Trust me. These are two very different unrelatred things.

> is actually used by the browser), or do they typically set this value to

Browsers do not use this at all I'm quite sure.

> sit in the ESTABLISHED state?

Until the server closes it IMHO. The server will close the connection due
to inactivity; 30 seconds by default for iPlanet web server.

---

From: John Stracke <[email-masked]>
Date: Thu, 02 Nov 2000 11:00:47 -0500

> is actually used by the browser), or do they typically set this value to

Sane applications typically do not use TCP keepalives.  TCP keepalives are a way
of consuming bandwidth in order to make your application less reliable.

See, keepalives are misnamed; idle TCP connections will be kept alive
indefinitely by default.  Using keepalives means you send an empty ACK every so
often to see if the remote host is still up.  The problem is that sending that
keepalive will also mean you drop the connection if some intermediate router is
down.  But, if your link is idle, you don't care whether an intermediate router
is down; you only care when you want to send data.  So keepalives just add
another way for your application to fail.

--
/==============================================================\
|John Stracke    | http://www.ecal.com |My opinions are my own.|
|Chief Scientist |=============================================|
|eCal Corp.      |Two words that do not go together: "Memorial |
[email-masked]|Cookbook".                                   |
\==============================================================/

---

From: Marc Slemko <[email-masked]>
Date: Thu, 2 Nov 2000 09:20:56 -0800 (PST)

> If you don't use it you lose it.

It is fair to say that the client has no idea of what sort of resource 
limits the server may have, so it should leave the connection open 
unless it has some particular reason (eg. wanting to limit the total
number of connections it has open to all servers) to close it.  In 
reality, common browsers probably put some fixed time limit on how long
they keep a connection open; if anyone wants to know exactly what 
whatever browsers they are concerned with do, try it.

On the same token, the server has no great desire to arbitrarily close 
connections, so it will leave it open unless it has some "reason" to 
close it.  Currently, many servers use a very simple metric for this,
which is a fixed timeout of x seconds after the last response was 
sent.  This is arguably a very poor metric to use, there has been some 
small amount of research on adaptive keepalive timeouts based on load.
The server, however, has a lot more information on which to base a decision
to close a connection.

It isn't that this sort of behaviour doesn't follow the spec, but simply
that there is no need to embed this sort of runtime information in a
protocol spec.  If you read the spec carefully, you will note it goes to
great lengths to ensure that the server may close the connection whenever
it is idle, which requires things like a half-duplex close, etc.

The bottom line, however, is that if you open a connection and make 
one request every few hours, I really don't see why you should care
if it is persistent or not, since persistent connections are just an
optimization.

> and its time to give some other poor slob a turn.

Huh?  That would be a webserver with some very... odd ideas.

If you are talking about "Connection: Keep-Alive" then you appear to be
talking about HTTP/1.0, in which there is no chunked encoding so
unless the server puts a content-length on its dynamic content
(which is perfectly possible for it to do, but many don't for
reasons that are also perfectly legitimate) then there is no way
to use a persistent connection since in that case the only
end-of-reponse marker you have is the close of connection.

> is written and the way that web server's are actually designed

The HTTP spec also doesn't describe what sort of config files you
should use for your server, since that isn't part of the protocol either.

> into the pipe. They are simply discarded.

Umh... again, your reasoning here is a little confused.  Closing the 
connection after sending the response to a POST by no means ensures that
this problem is avoided and, at that state of the game, is pointless.

It is legitimate to send a non-idempotent request with several idempotent
requests pipelined after it.

I think you are again getting confused by the requirement for a
content-length or chunking or the lack of a response body in order to
do persistent connections.

---

From: Marc Slemko <[email-masked]>
Date: Thu, 2 Nov 2000 10:18:47 -0800 (PST)

On Thu, 2 Nov 2000, James Lacey wrote:

> As a concrete example the iPlanet Enterprise v4.1 server always
> closes the connection after responding to a POST request or
> anytime that dynamic content is generated (possibly because
> the response does not have a Content-Length: header field
> and the response is not chunked).
> 
> I have verified this and it is clearly documented in their
> literature.

You are missing the point; it doesn't do it out of some odd desire
to "share" since a client has "had it's fill of dynamic content
for now", like you suggested it does.

---

From: James Lacey <[email-masked]>
Date: Thu, 02 Nov 2000 11:59:01 -0600

> do persistent connections.

Nope. I'm clear on that. All I was trying to say was that some
web servers always close the connection after they have processed
what they believe to be a non-idempotent request; iPlanet is
a case in point.

---

From: James Lacey <[email-masked]>
Date: Thu, 02 Nov 2000 13:22:08 -0600

> for now", like you suggested it does.

OK. OK. I get your point.

It may not be out of some odd desire to "share".

But it is certainly based on the idea that many
clients need to be serviced with relatively few
connections.

---

From: "Joris Dobbelsteen" <[email-masked]>
Date: Sun, 5 Nov 2000 18:01:08 +0100

> From: [email-masked] 
> [mailto:[email-masked]]On Behalf Of
> James Lacey
> Sent: Thursday, 02 November 2000 20:22
> To: Marc Slemko
> Cc: http-wg
> Subject: Re: Of HTTP/1.1 persistent connections and TCP 
> Keepalive timers
> 
> 
> Marc Slemko wrote:
> 
Some servers can close a connection after sending dynamic content because of security resons. (or because they are bad implementations.)

As for POST, if a server responds (except the 1xx status codes), the request must have ended. At least, this is the most logic thing for me. Also I don't know how to send a POST request without using content-length or chunked encoding and having the server knowning absolutely sure that request has ended.

- Joris