8 · HTTP ★
Slides 2-16 → 2-46 (minus caching) · HW2 P0, P1, P2
HTTP basics
- HTTP (hypertext transfer protocol) = the Web's application-layer protocol. Client-server: the browser requests objects, the Web server sends them.
- A Web page = a base HTML file plus referenced objects (images, scripts…), each with its own URL.
- HTTP uses TCP, port 80. The client opens a TCP connection, they exchange HTTP messages, and the connection closes.
- HTTP is stateless: the server keeps no information about past requests. (Keeping state is complex: if one side crashes, the two views of the state can disagree.)
Two kinds of connections
| Non-persistent (HTTP/1.0) | Persistent (HTTP/1.1, the default) |
|---|---|
| Open a TCP connection, send at most one object, close it | The server leaves the connection open after responding |
| Multiple objects → multiple connections | Multiple objects go over one connection |
| 2 RTT per object, plus OS overhead for every connection | As little as 1 RTT for all the referenced objects |
| Browsers open parallel connections to speed things up | With pipelining, the client sends requests as soon as it finds each referenced object |
• No pipelining: send GET 1 → wait for object 1 → send GET 2 → wait… That's 1 RTT per object.
• Pipelining: send GET 1, GET 2, …, GET 8 all at once → the responses stream back. That's about 1 RTT for all of them.
It's the same idea as segmentation in topic 4: keep the pipe full instead of waiting for each step to finish.
Where "2 RTT" comes from
RTT (round-trip time) = time for a small packet to go from client to server and back.
- 1 RTT to set up the TCP connection (client says hi, server says hi back).
- 1 RTT for the HTTP request to go out and the first bits of the response to come back.
- Plus the time to transmit the file.
Most problems say "neglect transmission time", so the \(L/R\) drops out.
The recipe (memorize this)
The page has a base HTML file and \(k\) referenced objects, all on the same server. \(\text{RTT}_0\) = RTT to that server.
| Mode | Time for the \(k\) objects |
|---|---|
| Non-persistent, no parallel | \(k \cdot 2\,\text{RTT}_0\) |
| Non-persistent, \(p\) parallel connections | \(\lceil k/p \rceil \cdot 2\,\text{RTT}_0\) (number of "rounds" × 2 RTT) |
| Persistent, no pipelining | \(k \cdot \text{RTT}_0\) (one request at a time, no new handshakes) |
| Persistent, with pipelining (default) | \(\text{RTT}_0\) (all requests sent back-to-back) |
• The base HTML always costs 2 RTT₀, even with persistent HTTP: the TCP connection has to be set up first. Persistence only saves time on the later objects.
• The browser can't request the objects until it has parsed the HTML, so the objects always come after the base file. Don't fold them into the same round.
• DNS happens once, before anything else. It's \(\text{RTT}_1 + \dots + \text{RTT}_n\) (one RTT per DNS server, no handshake, because DNS uses UDP).
• Parallel rounds use the ceiling: 8 objects, 6 connections → 6 then 2 → 2 rounds, not 1.33.
• If transmission time is not neglected, add \(L/R\) for each object that's sent.
Worked example: HW2 P0
Q: Click a link. The IP isn't cached, so DNS visits \(n\) servers with RTTs \(\text{RTT}_1, \dots, \text{RTT}_n\). The page is one object (small HTML). \(\text{RTT}_0\) = RTT to the Web server. Zero transmission time. Total time?
$$T = \mathbf{\text{RTT}_1 + \dots + \text{RTT}_n + 2\,\text{RTT}_0}$$DNS to get the IP, then 1 RTT for the TCP handshake and 1 RTT for the request/response.
Worked example: HW2 P1
Q: An HTTP client wants a URL, but the server's IP address is unknown. Which transport and application protocols besides HTTP are needed?
- Application layer: DNS (to get the IP address) and HTTP.
- Transport layer: UDP for DNS, TCP for HTTP.
Worked example: HW2 P2
Q: Same as P0, but the HTML references 8 very small objects on the same server. Neglect transmission times.
(a) Non-persistent, no parallel connections
Every object needs its own connection: 8 × 2 RTT₀.
$$\text{RTT}_1 + \dots + \text{RTT}_n + 2\,\text{RTT}_0 + 8 \times 2\,\text{RTT}_0 = \mathbf{18\,\text{RTT}_0 + \text{RTT}_1 + \dots + \text{RTT}_n}$$(b) Non-persistent, 6 parallel connections
\(\lceil 8/6 \rceil = 2\) rounds (6 objects, then the last 2), each 2 RTT₀.
$$\text{RTT}_1 + \dots + \text{RTT}_n + 2\,\text{RTT}_0 + 2 \times 2\,\text{RTT}_0 = \mathbf{6\,\text{RTT}_0 + \text{RTT}_1 + \dots + \text{RTT}_n}$$(c) Persistent HTTP (with pipelining, the default)
The connection is already open, and all 8 requests go out back-to-back: 1 RTT₀.
$$\text{RTT}_1 + \dots + \text{RTT}_n + 2\,\text{RTT}_0 + \text{RTT}_0 = \mathbf{3\,\text{RTT}_0 + \text{RTT}_1 + \dots + \text{RTT}_n}$$Side by side (just the RTT₀ part)
| Mode | Base HTML | 8 objects | Total |
|---|---|---|---|
| Non-persistent, serial | 2 | 8 × 2 = 16 | 18 RTT₀ |
| Non-persistent, 6 parallel | 2 | 2 × 2 = 4 | 6 RTT₀ |
| Persistent, no pipelining | 2 | 8 × 1 = 8 | 10 RTT₀ |
| Persistent, pipelined | 2 | 1 | 3 RTT₀ |
Then add the DNS sum to every row.
HTTP messages
Two types: request and response. Both are ASCII (human-readable). Every line ends in \r\n (carriage return, line feed), and a blank line marks the end of the header lines.
Request
GET /index.html HTTP/1.1 ← request line: method, URL, version
Host: www-net.cs.umass.edu ← header lines
User-Agent: Firefox/3.6.10
Connection: keep-alive
← blank line, then the (optional) body
| Method | What it does |
|---|---|
| GET | Request an object. Can also send user data in the URL after a ? (e.g. animalsearch?monkeys&banana) |
| POST | Send user input (e.g. a form) to the server in the entity body |
| HEAD | Ask for only the headers a GET would return, not the object |
| PUT | Upload a new file to the server, completely replacing the file at that URL |
Response status codes (first line of the response)
| Code | Meaning |
|---|---|
| 200 OK | Request succeeded. The object is later in this message |
| 301 Moved Permanently | Object moved. New location is in the Location: header |
| 400 Bad Request | Server didn't understand the request |
| 404 Not Found | Requested document isn't on this server |
| 505 HTTP Version Not Supported |
Also coming up in topic 9: 304 Not Modified (conditional GET). The response uses a Content-Length: header to say how long the body is (that's HW2 P4, topic 10).
Cookies: keeping state on a stateless protocol
Four components:
- A
Set-cookie:header line in the HTTP response - A
Cookie:header line in the next HTTP requests - A cookie file on the user's host, managed by the browser
- A back-end database at the Web site
Flow: Susan visits Amazon for the first time. The server creates a unique ID (say 1678) and a database entry for it, and replies with Set-cookie: 1678. Her browser stores it. Every later request to Amazon, even a week later, carries Cookie: 1678, so the site recognizes her and takes a cookie-specific action.
- Uses: authorization, shopping carts, recommendations, user session state (Web email).
- Privacy: first-party cookies track you on one site. Third-party (tracking) cookies track you across many sites, without you ever visiting the tracker (e.g. through ads or invisible links). Firefox and Safari block third-party cookies by default.
HTTP/2 and HTTP/3
Goal of both: less delay for pages with many objects.
| Version | Key points |
|---|---|
| HTTP/1.1 | Pipelined GETs over one TCP connection, but the server replies in order (FCFS). A small object can get stuck behind a big one: head-of-line (HOL) blocking. A lost TCP segment also stalls everything. |
| HTTP/2 (2015) | Same methods, status codes and most headers. Sends objects by client-specified priority, not FCFS. Can push unrequested objects. Splits objects into frames and interleaves them to reduce HOL blocking (small objects arrive fast, the big one is only slightly delayed). |
| HTTP/3 | HTTP/2 still runs over one TCP connection, so packet loss still stalls every object, and plain TCP has no security. HTTP/3 runs over QUIC over UDP, adding security plus per-object error and congestion control. |
QUIC (Quick UDP Internet Connections) is an application-layer protocol on top of UDP. It sets up reliability, congestion control, authentication, encryption and state in one RTT, and multiplexes many streams over one connection.
Quick check
1. DNS visits 3 servers (RTTs 10, 20, 30 ms). RTT₀ = 50 ms. One small HTML object, no transmission time. Total time?
$$60 + 2(50) = \mathbf{160 \text{ ms}}$$2. Same setup, but the HTML references 5 small objects. Non-persistent, no parallel connections?
$$60 + 2(50) + 5 \times 2(50) = 60 + 100 + 500 = \mathbf{660 \text{ ms}}$$3. Same as #2, with 3 parallel connections?
\(\lceil 5/3 \rceil = 2\) rounds. $$60 + 100 + 2 \times 100 = \mathbf{360 \text{ ms}}$$4. Same as #2, persistent with pipelining? Without pipelining?
With pipelining: \(60 + 100 + 50 = \mathbf{210 \text{ ms}}\).Without pipelining: \(60 + 100 + 5 \times 50 = \mathbf{410 \text{ ms}}\).
5. 10 objects, non-persistent, 5 parallel connections, DNS already cached. Answer in RTT₀.
\(2\,\text{RTT}_0 + \lceil 10/5 \rceil \times 2\,\text{RTT}_0 = 2 + 4 = \mathbf{6\,\text{RTT}_0}\).6. Non-persistent, one 1 Mbit object, R = 10 Mbps, RTT = 20 ms. Response time (no DNS)?
$$2(20) + \frac{10^6}{10^7} \text{ s} = 40 + 100 = \mathbf{140 \text{ ms}}$$7. Why does the base HTML still cost 2 RTT with persistent HTTP?
The TCP connection doesn't exist yet: 1 RTT to set it up, 1 RTT to request and receive the HTML. Persistence only helps the objects after that.8. What does "HTTP is stateless" mean, and how do sites remember you anyway?
The server keeps no information about past client requests. Sites use cookies: the server sendsSet-cookie with an ID, the browser stores it and sends it back in every later request, and the site looks the ID up in its back-end database.9. What's the difference between 301 and 404?
301 Moved Permanently: the object exists somewhere else (new URL in theLocation: header). 404 Not Found: the document isn't on this server.