3

says a client has multiple files to post to a server via HTTP Post method, there will be two api calls. since I don't want to create two TCP connections and I want to reuse TCP connection, so I use Http keep-alive header for the first request, now I only need a single TCP connection established at the first request to send multiple files

But how does the server distinguish between those two files? When we don't use keep alive, the client's OS sends EOF flag (end of file) to indicate the server that the a file has been completed transmitted

below is my assumption, not sure if it is correct:

Now we use keep-alive, so an EOF on the server doesn't close the connection, so a second file can be sent over the same connection and end with EOF. But how does client close the TCP connection when he doesn't want to send any more file? if the client sends another EOF, the server might think he is going to send another file?

the only think I can think of is that, let's say you only have 5 files to send, on the 5th HTTP request, you don't send keep-alive header, but 1st, 2nd, 3rd and 4th request all need to be sent with keep-alive header, is my understanding correct?

3 Answers 3

10

When we don't use keep alive, the client's OS sends EOF flag (end of file) to indicate the server that the a file has been completed transmitted

No, it doesn't. The end of an HTTP request is detected either by receiving the delimiting empty line (for requests with no body), or by reading the exact amount of bytes specified in the request's "Content-Length" header (for requests with a fixed-length body), or by reading a 0-byte chunk (for chunked requests).

The RFC 9112 linked from the other answer talks about message framing in great detail, section 6.3 "Message Body Length" in particular.

Now we use keep-alive, so an EOF on the server doesn't close the connection, so a second file can be sent over the same connection and end with EOF

That's not correct. TCP has no other way of "sending an EOF flag" except by closing the sender's side of the connection (the shutdown(SHUT_WR) operation), which is final – no more data can be sent in that direction, and it usually leads to a shutdown in the other direction as well.

More generally, "EOF" is not an actual message; in programming languages it is determined by the absence of a message – EOF is raised after getting a 0-byte result from the read() operation. But TCP has no way to signal this arbitrarily, because it does not report message boundaries to the receiver; it literally cannot deliver a 0-byte message. (In fact empty TCP segments are often used as a "keep-alive" mechanism specifically because they don't cause the receiver to see a 0-byte read.)

(In other words: You don't close a TCP connection by signalling EOF – you signal EOF by closing the TCP connection.)

This is why RFC 9112 uses the term 'close', e.g. in "Request messages are never close-delimited […]" instead of "EOF-delimited".

1
  • TCP has a FIN flag to indicate EOF. In the sockets API you send this either by closing the socket or using the shutdown() call with the SHUT_WR argument.
    – Barmar
    Apr 18 at 14:55
5

The Connection: keep-alive header is implicit with HTTP/1.1, i.e. only needed with HTTP/1.0. And in persistent HTTP/1 one request is send after the other and the responses come back in the same order. HTTP/1 also defines clearly where a message (request, response) ends (Content-Length, Transfer-Encoding headers) so an application which properly implements HTTP/1 can detect the message boundaries.

For the specific technical details see the standard

2

If the client sends an EOF, they can't send another file over the same connection. Unlike files and terminals, EOF in TCP is a permanent condition fopr that connection. It's signaled by sending a segment containing the FIN flag, and no further data can be sent other than acknowledgements of segments sent from the other end.

When keep-alives are used, a different method is used to indicate where the end of the data being sent is. If the size of the data is known before transmission, a Content-Length header is usually sent, and the receiver simply reads that many bytes. If the data is being generated dynamically, Transfer-Encoding: chunked is used. This sends the data as a sequence of <data-size><data-bytes> chunks, with the end signaled by sending a chunk with size 0. Chunked encoding is most often used in dynamic replies from servers that are generated by scripts, rather than uploading and downloading files, since the file size can be determined before sending it.

3
  • Thanks for your answer. So if a client app want to re-use a single TCP connection to make multiple request to a same host, since EOF cannot be sent to keep connection open, then each client's request has to specify the content length of the sending file for the server to re-assembly, is my understanding correct? also does client needs to send periodical dummy data to the server to keep TCP connection open as the server might close the connection due to inactive client? Apr 19 at 8:53
  • Yes, that's exactly how it works. Persistent connections are generally only used for requests that are sent in rapid order, the client should close the connection if it doesn't have anything new to send right away. Servers will also close idle connections after a timeout. The client shouldn't send dummy requests just to keep it open, as this is wasting server resources.
    – Barmar
    Apr 19 at 15:30
  • The intended use is for when you're loading an HTML page and it has lots of images, scripts, CSS files -- you can use multiple and persistent connections to fetch all of them efficiently. But once you're done, you close the connection.
    – Barmar
    Apr 19 at 15:33

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .