At the top of the stack, programs talk in application protocols. Two of them are behind every web page you open.
DNS: names to addresses
People remember example.com; packets need 93.184.216.34. The Domain Name System is a distributed database of names, spread over millions of servers:
- Your computer asks a resolver (usually run by your ISP, or a public one like 1.1.1.1).
- If the resolver does not know the answer, it asks a root server: "who handles
.com?" - The
.comTLD server answers: "ask the servers forexample.com". - Those authoritative servers give the address.
Every answer has a TTL (time to live), and the resolver caches it that long, so most questions never reach the root at all.
authoritative = {"example.com": ("93.184.216.34", 300), "codebase.dev": ("76.76.21.21", 60)}
cache = {} # name -> (address, expires at)
def resolve(name, now):
if name in cache and cache[name][1] > now:
return cache[name][0] + " (cached)"
address, ttl = authoritative[name] # root -> TLD -> authoritative
cache[name] = (address, now + ttl)
return address + " (asked the servers)"
for now, name in [(0, "example.com"), (10, "example.com"), (100, "codebase.dev"), (200, "codebase.dev")]:
print("t =", now, name, "->", resolve(name, now))| Record | Holds | Example |
|---|---|---|
| A | an IPv4 address | example.com → 93.184.216.34 |
| AAAA | an IPv6 address | example.com → 2606:2800:220:1:: |
| CNAME | another name (an alias) | www.example.com → example.com |
| MX | the mail server for a domain | example.com → mail.example.com |
DNS mostly uses UDP port 53: one small question, one small answer.
HTTP: what browsers and servers say
HTTP is text (in versions 1.x): a request line, header lines, a blank line, and an optional body. The server answers with a status line, headers, a blank line and the page.
request = "GET /about.html HTTP/1.1\r\nHost: example.com\r\nAccept: text/html\r\nCookie: theme=dark\r\n\r\n"
head, body = request.split("\r\n\r\n", 1)
lines = head.split("\r\n")
method, path, version = lines[0].split(" ")
headers = {}
for line in lines[1:]:
name, value = line.split(": ", 1)
headers[name] = value
print("method:", method, " path:", path, " version:", version)
print("headers:", headers)
print("body:", repr(body))| Status | Meaning |
|---|---|
| 200 OK | here it is |
| 301 / 302 | it moved: see the Location header |
| 404 Not Found | no such page |
| 500 | the server had an error |
Methods say what to do: GET reads, POST sends data (a form), PUT and DELETE change and remove. HTTP is stateless: each request stands alone, so websites use cookies (a header the browser sends back every time) to remember who you are.
HTTPS is HTTP inside TLS on port 443: the connection is encrypted, and the server proves who it is with a certificate. Today almost every site uses it. HTTP/2 and HTTP/3 keep the same requests and answers but send them in binary, many at once on one connection (HTTP/3 over UDP).
Common mistakes
- Thinking DNS goes to the root server for every lookup: caching answers most questions near you.
- Forgetting the blank line between headers and body in a raw HTTP message.
- Thinking HTTPS hides which site you visit. It hides the pages and data, but the site's name and IP address are still visible to the network.
Quick check
My notes
Write down what you want to remember from this lesson. Notes are saved on this device as you type, and appear on your dashboard.