Computer Systems: A Programmer's Perspective Chương 11 · Network Programming

Chương 11 · Lập trình mạng Chapter 11 · Network Programming

Mọi ứng dụng mạng đều dựng trên một mô hình: khách gửi yêu cầu, chủ trả lời Các chương trình nói chuyện với nhau qua mạng như thế nào Every network application is built on one model: a client asks, a server answers

Bryant và O'Hallaron mở chương bằng một khẳng định gọn: mọi ứng dụng mạng — trình duyệt web, thư điện tử, trò chơi trực tuyến — đều dựa trên cùng một mô hình khách-chủ (client-server model), có cùng cấu trúc logic và dựa trên cùng một giao diện lập trình.1 Để chứng minh, hai ông dẫn người đọc từ mô hình trừu tượng ấy xuống tới một máy chủ web (web server) thật tên là TINY, chỉ gói gọn trong khoảng 250 dòng mã mà phục vụ được cả nội dung tĩnh lẫn động cho trình duyệt thật.1

Mỗi khi bạn mở một trang web hay gửi một email, có hai chương trình đang nói chuyện: một bên hỏi (máy khách) và một bên trả lời (máy chủ). Dù là web, email hay trò chơi, cách chúng bắt tay nhau đều giống nhau. Cuối chương, các tác giả còn tự viết một máy chủ web tí hon chỉ 250 dòng mà chạy được với trình duyệt thật. Nhớ nhé: trên mạng, luôn có một bên hỏi và một bên đáp.

Bryant and O'Hallaron open with a compact claim: every network application — web browser, email, online game — is based on the same client-server model, shares the same logical structure, and relies on the same programming interface.1 To prove it, they lead the reader from that abstract model down to a real web server called TINY, just about 250 lines of code that serves both static and dynamic content to real browsers.1

Điểm tinh tế của chương là nó đứng ở góc nhìn của lập trình viên: không sa vào chi tiết nội bộ của giao thức mạng, mà chỉ trình bày đúng những khả năng mà TCP và IP cung cấp cho chương trình ứng dụng. Các khái niệm cũ — tiến trình, tín hiệu, thứ tự byte (byte ordering), ánh xạ bộ nhớ, cấp phát động — đều được tái sử dụng; cái mới cần nắm là mô hình khách-chủ và cách viết chương trình khách-chủ dùng dịch vụ của Internet.1 Chính vì vậy, với một hệ thống đơn lẻ, các tác giả nhấn mạnh: mạng chỉ là một thiết bị vào–ra (I/O device) nữa — nguồn và đích của dữ liệu, không khác gì đĩa hay bàn phím.1

Luận đề của chương: mọi ứng dụng mạng đều quy về một mô hình khách-chủ chạy trên Internet IP toàn cầu; lập trình viên nối hai tiến trình qua một kết nối (connection) nhờ giao diện ổ cắm (sockets interface), và trên nền ấy dựng nên các giao thức tầng ứng dụng như HTTP — tất cả đủ để tự tay viết một máy chủ web hoạt động được.1

Ý chính: internet cho hai chương trình ở hai nơi nói chuyện được với nhau. Người lập trình chỉ cần một công cụ gọi là “ổ cắm” để nối chúng lại, rồi thống nhất một “ngôn ngữ” chung (như HTTP) là đủ dựng được một trang web. Nhớ nhé: nối hai bên bằng ổ cắm, cho chúng chung một ngôn ngữ, thế là thành ứng dụng mạng.

The chapter's thesis: every network application reduces to a client-server model running over the global IP Internet; the programmer joins two processes through a connection using the sockets interface, and on top of that builds application-level protocols such as HTTP — enough to write a working web server by hand.1

Cụm khái niệm 01 Concept cluster 01

Mô hình khách-chủ, và mạng chỉ là một thiết bị vào–ra Một bên hỏi, một bên đáp — và “mạng” thật ra là gì The client-server model, and a network is just an I/O device

Nền tảng của mọi ứng dụng mạng là mô hình khách-chủ (client-server model): một ứng dụng gồm một tiến trình chủ và một hay nhiều tiến trình khách. Máy chủ quản lý một tài nguyên nào đó và phục vụ khách bằng cách thao tác trên tài nguyên ấy — ví dụ máy chủ web quản lý một tập tệp trên đĩa.1 Thao tác cơ bản là một giao dịch (transaction) gồm bốn bước: khách gửi yêu cầu, chủ xử lý, chủ gửi phản hồi, khách xử lý phản hồi.1

Mọi ứng dụng mạng đều có hai vai: một bên phục vụ (máy chủ, giữ tài nguyên) và một bên nhờ vả (máy khách). Cuộc trao đổi diễn ra như hỏi và đáp ở quán ăn: khách gọi món, bếp làm, bếp bưng ra, khách ăn. Nhớ nhé: khách gọi, chủ làm rồi đưa, khách nhận — cứ thế lặp lại.

The foundation of every network application is the client-server model: an application consists of one server process and one or more client processes. The server manages some resource and serves clients by manipulating it — for example, a web server manages a set of disk files.1 The basic operation is a transaction of four steps: the client sends a request, the server processes it, the server sends a response, and the client processes the response.1

Định nghĩa. Điều cốt yếu: khách và chủ là các tiến trình, chứ không phải các máy (host). Một host duy nhất có thể chạy nhiều khách và nhiều chủ cùng lúc, và một giao dịch khách-chủ có thể nằm trên cùng một host hoặc trên hai host khác nhau — mô hình vẫn như nhau.1

Nói đơn giản. “Khách” và “chủ” là hai vai trò của chương trình, không phải hai cái máy. Một máy có thể vừa là khách vừa là chủ của nhiều cuộc trò chuyện. Nhớ nhé: khách và chủ là vai, không phải máy.

Definition. The key point: clients and servers are processes, not machines (hosts). A single host can run many clients and servers at once, and a client-server transaction can be on the same host or on two different hosts — the model is the same.1

1. khách --[request]--> chủ
2. chủ xử lý tài nguyên
3. chủ --[response]--> khách
4. khách xử lý phản hồi

khách hỏi --> chủ làm
  --> chủ đáp --> khách nhận

1. client --[request]--> server
2. server manipulates resource
3. server --[response]--> client
4. client processes response

  1. client-server model

    Mô hình khách-chủ — bộ khung chung cho mọi ứng dụng mạng Mô hình khách-chủ — khuôn mẫu chung của mọi ứng dụng mạng The client-server model — the common frame for all network apps

    Dù là web, FTP hay thư điện tử, mỗi dịch vụ đều là một máy chủ quản lý tài nguyên của riêng nó và phục vụ khách qua giao dịch bốn bước.1 Các tác giả lưu ý: giao dịch khách-chủ ở đây không phải giao dịch cơ sở dữ liệu và không có các tính chất như nguyên tử (atomicity) — nó chỉ là một chuỗi bước do khách và chủ thực hiện.1

    Web, email hay tải tệp — tất cả đều theo cùng một khuôn: có người giữ đồ (máy chủ) và người xin đồ (máy khách), trao đổi qua lại. Học một mẫu là hiểu được tất cả. Nhớ nhé: nắm một khuôn khách-chủ là hiểu mọi ứng dụng mạng.

    Whether web, FTP, or email, each service is a server managing its own resource and serving clients through the four-step transaction.1 The authors caution: a client-server transaction here is not a database transaction and has none of its properties such as atomicity — it is just a sequence of steps carried out by a client and a server.1

    Bạn gặp nó ở đâuWhere you meet it Mỗi lần trình duyệt cần một tệp, nó gửi yêu cầu tới máy chủ web; máy chủ đọc tệp trên đĩa rồi gửi lại — đúng bốn bước của giao dịch.1 Khi bạn bấm vào một đường link, trình duyệt đang “gọi món” với một máy chủ ở xa. Every time a browser needs a file, it sends a request to a web server; the server reads the file from disk and sends it back — the four transaction steps exactly.1
  2. network as I/O

    Mạng — với một host, chỉ là một thiết bị vào–ra nữa Mạng — với mỗi máy, giống như một cổng vào–ra khác The network — to a host, just another I/O device

    Dưới góc nhìn của một host, mạng chỉ là một thiết bị vào–ra làm nguồn và đích cho dữ liệu: một bộ điều hợp mạng (network adapter) cắm vào khe mở rộng trên bus I/O, và dữ liệu được chép giữa bộ điều hợp và bộ nhớ, thường bằng truyền DMA.1 Về mặt vật lý, mạng là hệ thống phân cấp theo địa lý: dưới cùng là LAN (local area network); công nghệ LAN phổ biến nhất là Ethernet, ra đời giữa thập niên 1970 tại Xerox PARC, mỗi bộ điều hợp mang một địa chỉ 48 bit duy nhất toàn cầu.1

    Máy tính coi mạng y như một thiết bị vào–ra khác, giống đĩa hay bàn phím — chỉ là chỗ dữ liệu đi ra và đi vào. Có một miếng phần cứng gọi là “card mạng” lo việc đó. Nhớ nhé: với máy tính, mạng cũng chỉ là một cửa ra–vào của dữ liệu.

    From a host's viewpoint, the network is just another I/O device serving as a source and sink for data: a network adapter plugs into an expansion slot on the I/O bus, and data is copied between adapter and memory, typically by DMA transfer.1 Physically, a network is a hierarchy organized by geography: at the bottom is a LAN; the most popular LAN technology is Ethernet, developed in the mid-1970s at Xerox PARC, each adapter carrying a globally unique 48-bit address.1

    Bạn gặp nó ở đâuWhere you meet it Nhiều phân đoạn Ethernet nối thành LAN lớn hơn qua các cầu (bridge); các LAN và WAN khác nhau lại nối qua bộ định tuyến (router) để tạo thành một internet.1 Nhiều mạng nhỏ nối lại với nhau bằng những hộp định tuyến để thành mạng lớn. Multiple Ethernet segments join into bigger LANs via bridges; different LANs and WANs join via routers to form an internet.1

    Ethernet bền bỉ

    Sách ghi nhận Ethernet đã tỏ ra bền bỉ đáng kinh ngạc, tiến hoá từ 3 Mb/s lên tới 10 Gb/s; một phân đoạn gồm dây xoắn và một hộp nhỏ gọi là hub, chép mọi bit nhận được ở mỗi cổng sang mọi cổng khác.1

    internet (thường) so với Internet

    Các tác giả dùng “internet” viết thường cho khái niệm chung (mạng của các mạng), và “Internet” viết hoa cho một hiện thực cụ thể — chính là Internet IP toàn cầu bàn ở phần sau.1

  3. encapsulation

    Đóng gói — chìa khoá để các mạng không tương thích nói chuyện Đóng gói — bí quyết cho các mạng khác loại hiểu nhau Encapsulation — the key to bridging incompatible networks

    Làm sao dữ liệu đi được qua các LAN/WAN có công nghệ khác nhau và không tương thích? Lời giải là một tầng phần mềm giao thức (protocol software) chạy trên mọi host và router, cung cấp hai khả năng: một sơ đồ đặt tên thống nhất (mỗi host có một địa chỉ internet duy nhất) và một cơ chế phân phát gói dữ liệu vào các khối gọi là gói tin (packet) gồm phần đầu (header) và phần tải (payload).13

    Mỗi mạng nói một “tiếng” khác nhau. Bí quyết để chúng hiểu nhau là bọc dữ liệu vào những phong bì có địa chỉ thống nhất, rồi lồng phong bì nhỏ vào phong bì lớn khi đi qua từng mạng. Nhớ nhé: bọc dữ liệu thành gói có địa chỉ chung thì mạng nào cũng chuyển được.

    How does data cross LANs/WANs of different, incompatible technologies? The answer is a layer of protocol software running on every host and router, providing two capabilities: a uniform naming scheme (each host gets a unique internet address) and a delivery mechanism that bundles data into chunks called packets with a header and a payload.13

    Bạn gặp nó ở đâuWhere you meet it Khi một khung LAN1 mang trong nó một gói internet, mà gói ấy lại mang dữ liệu người dùng — kiểu lồng nhau này chính là đóng gói (encapsulation), một hiểu biết nền tảng của internetworking.1 Giống như bỏ thư vào phong bì, rồi bỏ phong bì vào một túi lớn hơn khi chuyển qua bưu cục khác. When a LAN1 frame carries an internet packet inside it, which in turn carries the user data — this nesting is encapsulation, a fundamental insight of internetworking.1

    Tám bước qua một router

    Sách mô tả tỉ mỉ tám bước dữ liệu đi từ host A (LAN1) tới host B (LAN2) qua một router: host A chép dữ liệu xuống đệm nhân, phần mềm giao thức bọc thêm header gói và header khung, router đọc địa chỉ đích rồi tra bảng định tuyến (routing table), tháo header khung cũ, gắn header khung mới, và chuyển tiếp — đóng gói là chìa khoá.1

    Những gì còn bỏ ngỏ

    Các tác giả thừa nhận đã lướt qua nhiều vấn đề khó: kích thước khung tối đa khác nhau giữa các mạng, cách router biết chuyển tiếp đi đâu, và điều gì xảy ra khi một gói tin bị mất — những câu hỏi mà giao thức tầng trên (như TCP) phải giải quyết.1

Cụm khái niệm 02 Concept cluster 02

Internet IP toàn cầu, và giao diện ổ cắm để nối hai tiến trình Internet, địa chỉ IP, và cách nối hai chương trình lại The global IP Internet, and the sockets interface that joins two processes

Internet IP toàn cầu là hiện thực nổi tiếng và thành công nhất của ý tưởng internet, tồn tại dưới dạng này hay dạng khác từ năm 1969. Mỗi host chạy phần mềm hiện thực họ giao thức TCP/IP; dưới góc nhìn của lập trình viên, Internet là một tập host toàn cầu với ba tính chất: mỗi host có một địa chỉ IP (IP address) 32 bit, tập địa chỉ IP được ánh xạ sang tập tên miền (domain name), và một tiến trình trên host này có thể nói chuyện với tiến trình trên host khác qua một kết nối (connection).123

Internet là mạng lớn nhất thế giới. Mỗi máy trên đó có một con số định danh gọi là địa chỉ IP, giống như số nhà. Vì số khó nhớ, người ta còn gắn cho máy một cái tên (tên miền) như google.com. Hai chương trình ở hai nơi nói chuyện với nhau qua một “đường dây” gọi là kết nối. Nhớ nhé: mỗi máy có một số nhà (IP) và một cái tên (tên miền).

The global IP Internet is the most famous and successful implementation of the internet idea, existing in one form or another since 1969. Each host runs software implementing the TCP/IP protocol family; from a programmer's view, the Internet is a worldwide set of hosts with three properties: each host has a 32-bit IP address, the set of IP addresses maps to a set of domain names, and a process on one host can talk to a process on another over a connection.123

Định nghĩa. Một ổ cắm (socket) là đầu mút của một kết nối. Mỗi socket có một địa chỉ socket gồm một địa chỉ IP và một số cổng (port) 16 bit, viết là địa_chỉ:cổng. Một kết nối được xác định duy nhất bởi cặp địa chỉ socket của hai đầu, gọi là cặp socket (socket pair).1

Nói đơn giản. “Ổ cắm” là một đầu dây của cuộc gọi, ghi rõ số nhà (IP) và số phòng (cổng). Hai đầu dây ghép lại thì xác định đúng một cuộc gọi. Nhớ nhé: ổ cắm = số nhà + số phòng; hai đầu ghép lại là một kết nối.

Definition. A socket is an end point of a connection. Each socket has a socket address consisting of an IP address and a 16-bit port, written address:port. A connection is uniquely identified by the pair of socket addresses of its two ends, the socket pair.1

socket pair:
(cliaddr:cliport, servaddr:servport)
vd: (128.2.194.242:51213,
    208.216.181.15:80)

(máy khách : cổng khách,
  máy chủ : cổng chủ)

socket pair:
(cliaddr:cliport, servaddr:servport)
e.g. (128.2.194.242:51213,
    208.216.181.15:80)

  1. IP addresses + DNS

    Địa chỉ IP và DNS — số nhà và danh bạ của Internet Địa chỉ IP và DNS — số nhà và cuốn danh bạ IP addresses & DNS — the Internet's house numbers and directory

    Một địa chỉ IP là số nguyên 32 bit không dấu, thường trình bày cho người đọc dưới dạng thập phân có dấu chấm (dotted-decimal): ví dụ 128.2.194.242 là cách viết của 0x8002c2f2.1 Vì các host có thứ tự byte khác nhau, TCP/IP quy định một thứ tự byte mạng (network byte order) thống nhất là big-endian cho mọi số nguyên trong header gói.1 Tên miền được ánh xạ sang địa chỉ IP qua DNS (Domain Name System), một cơ sở dữ liệu phân tán toàn cầu duy trì từ năm 1988.16

    Số nhà của máy tính là một con số 32 bit, viết cho dễ nhìn thành bốn số ngăn bởi dấu chấm như 128.2.194.242. Vì số khó nhớ, có một “cuốn danh bạ” khổng lồ tên là DNS để tra từ cái tên (như google.com) ra số nhà. Nhớ nhé: DNS là danh bạ đổi tên thành số nhà.

    An IP address is an unsigned 32-bit integer, usually shown to people in dotted-decimal form: e.g. 128.2.194.242 is the notation for 0x8002c2f2.1 Because hosts have different byte orders, TCP/IP mandates a uniform network byte order (big-endian) for any integer in a packet header.1 Domain names map to IP addresses via DNS (Domain Name System), a worldwide distributed database maintained since 1988.16

    Bạn gặp nó ở đâuWhere you meet it Mỗi host có tên localhost luôn ánh xạ tới địa chỉ vòng lặp (loopback) 127.0.0.1 — một cách tiện lợi và khả chuyển để trỏ tới client và server chạy trên cùng máy, rất hữu ích khi gỡ lỗi.1 Tên localhost (số 127.0.0.1) luôn trỏ về chính máy bạn — tiện để thử nghiệm. Every host has the name localhost, which always maps to the loopback address 127.0.0.1 — a convenient, portable way to reference a client and server on the same machine, handy for debugging.1

    Chuyển đổi địa chỉ

    Unix cung cấp htonl/htons (host sang network) và ntohl/ntohs (chiều ngược lại) cho số 32 và 16 bit; inet_pton và inet_ntop chuyển giữa chuỗi dotted-decimal và địa chỉ nhị phân — “n” là network, “p” là presentation.1

    IPv4 so với IPv6 — con số đã cũ

    Sách tập trung vào IPv4 (32 bit); IPv6 với địa chỉ 128 bit được IETF đề xuất năm 1996 làm bản kế nhiệm. Sách dẫn số liệu tính đến 2015: chỉ 4% người dùng truy cập dịch vụ Google qua IPv6.1 Cần lưu ý con số này đã lỗi thời: theo thống kê công khai của Google, tỉ lệ ấy đã tăng lên vùng 40–45% vào giữa thập niên 2020 — nên hãy đọc “4%” như một ảnh chụp năm 2015, không phải hiện trạng.7

  2. connections & ports

    Kết nối và cổng — điểm-tới-điểm, song công, đáng tin cậy Kết nối và cổng — một đường dây tin cậy giữa hai bên Connections & ports — point-to-point, full duplex, reliable

    Một kết nối là điểm-tới-điểm (nối đúng một cặp tiến trình), song công (full duplex) (dữ liệu chảy cả hai chiều cùng lúc), và đáng tin cậy (dòng byte đến nơi đúng thứ tự đã gửi).1 Cổng trong địa chỉ socket của khách do nhân cấp tự động khi tạo kết nối, gọi là cổng tạm (ephemeral port); còn cổng của chủ thường là cổng quen thuộc (well-known port) gắn cố định với dịch vụ — web dùng cổng 80, thư điện tử dùng cổng 25.1

    Kết nối là một đường dây nối đúng hai chương trình, cho nói hai chiều cùng lúc, và bảo đảm chữ gửi đi đến nơi đúng thứ tự. Mỗi dịch vụ ngồi ở một “số phòng” quen thuộc: web ở phòng 80, email ở phòng 25. Nhớ nhé: web luôn gõ cửa phòng số 80.

    A connection is point-to-point (it joins exactly one pair of processes), full duplex (data flows both ways at once), and reliable (the byte stream arrives in the order it was sent).1 The port in a client's socket address is assigned automatically by the kernel as an ephemeral port; the server's port is usually a well-known port fixed to the service — web uses port 80, email uses port 25.1

    Bạn gặp nó ở đâuWhere you meet it Trong ví dụ của sách, socket của khách web là 128.2.194.242:51213 (cổng 51213 là cổng tạm do nhân cấp) nối tới socket của chủ 208.216.181.15:80.1 Máy bạn dùng một số phòng tạm, còn máy chủ web luôn ở phòng 80. In the book's example, the web client's socket is 128.2.194.242:51213 (port 51213 is an ephemeral port from the kernel), connected to the server's socket 208.216.181.15:80.1

    TCP, IP và UDP

    TCP/IP là một họ giao thức: IP cung cấp sơ đồ đặt tên và cơ chế gửi các gói gọi là datagram, nhưng không đáng tin cậy — không nỗ lực khôi phục nếu gói mất hay bị nhân đôi. TCP là giao thức phức tạp xây trên IP để cung cấp kết nối song công đáng tin cậy giữa các tiến trình. UDP mở rộng IP nhẹ nhàng để datagram đi được từ tiến trình tới tiến trình.12

    Internet lớn cỡ nào

    Sách dẫn Internet Domain Survey: từ khoảng 20.000 host năm 1987, số host tăng theo cấp số nhân, và tới năm 2015 đã vượt 1.000.000.000 (một tỉ) host.1

  3. socket API

    Giao diện ổ cắm — socket, bind, listen, accept, connect Bộ hàm ổ cắm — những lệnh để nối hai chương trình The sockets interface — socket, bind, listen, accept, connect

    Giao diện ổ cắm là một tập hàm dùng chung với Unix I/O để dựng ứng dụng mạng. Khách và chủ đều gọi socket để tạo bộ mô tả ổ cắm (socket descriptor); khách gọi connect để thiết lập kết nối; còn chủ dùng bộ ba bind, listen, accept. Hàm listen biến một socket chủ động thành socket nghe (listening socket).15

    “Ổ cắm” đi kèm một bộ lệnh ngắn: tạo ổ cắm, rồi khách thì “gọi” (connect), còn chủ thì “gắn địa chỉ” (bind), “lắng nghe” (listen) và “nhận cuộc gọi” (accept). Học năm lệnh này là viết được chương trình mạng. Nhớ nhé: khách gọi connect, chủ thì bind–listen–accept.

    The sockets interface is a set of functions used with Unix I/O to build network applications. Both client and server call socket to create a socket descriptor; the client calls connect to establish a connection; the server uses the trio bind, listen, accept. The listen function turns an active socket into a listening socket.15

    Bạn gặp nó ở đâuWhere you meet it Sách phân biệt rõ bộ mô tả nghe (listening descriptor, ví dụ số 3) tồn tại suốt đời máy chủ, với bộ mô tả đã nối (connected descriptor, ví dụ số 4) mà accept tạo ra cho mỗi kết nối — chính sự phân biệt này cho phép dựng máy chủ đồng thời.1 Máy chủ có một “cửa chính” để nghe, và với mỗi khách lại mở một “đường dây riêng” để phục vụ. The book distinguishes the listening descriptor (e.g. 3), which lives for the server's lifetime, from the connected descriptor (e.g. 4) that accept creates per connection — this distinction is what enables concurrent servers.1

    getaddrinfo thay cho cách cũ

    Thực hành tốt nhất là dùng getaddrinfo để sinh tham số một cách độc lập với phiên bản IP; nó là bản thay thế hiện đại cho gethostbyname/getservbyname đã lỗi thời, có tính tái nhập (reentrant) và trả về danh sách liên kết các cấu trúc addrinfo.15

    Nguồn gốc Berkeley sockets

    Giao diện ổ cắm gốc do các nhà nghiên cứu ở Đại học California, Berkeley phát triển đầu thập niên 1980, nên thường gọi là Berkeley sockets; hiện thực đầu tiên cho TCP/IP được đưa vào nhân Unix 4.2BSD. Tham số backlog của listen thường đặt giá trị lớn, chẳng hạn 1.024.1

Cụm khái niệm 03 Concept cluster 03

Máy chủ web, giao thức HTTP, và máy chủ TINY Trang web hoạt động thế nào, và một máy chủ web tí hon Web servers, the HTTP protocol, and the TINY server

Khách và chủ web tương tác qua một giao thức (protocol) tầng ứng dụng dựa trên văn bản tên là HTTP (hypertext transfer protocol). Một trình duyệt mở kết nối Internet tới máy chủ, yêu cầu một nội dung; máy chủ trả về nội dung rồi đóng kết nối.1 Điều phân biệt web với dịch vụ truyền tệp thông thường là nội dung web có thể viết bằng HTML (hypertext markup language), trong đó một trang có thể chứa các con trỏ (siêu liên kết) tới nội dung trên bất kỳ host Internet nào.14

Web dùng một “ngôn ngữ” chung tên là HTTP: trình duyệt gõ cửa máy chủ và xin một trang, máy chủ đưa trang rồi gác máy. Trang được viết bằng HTML — thứ cho phép đặt các đường link nhảy tới trang khác ở bất cứ đâu. Nhớ nhé: HTTP là ngôn ngữ xin–cho của web.

Web clients and servers interact through a text-based application-level protocol called HTTP (hypertext transfer protocol). A browser opens an Internet connection to a server and requests some content; the server returns it and closes the connection.1 What distinguishes the web from ordinary file transfer is that web content can be written in HTML (hypertext markup language), in which a page can hold pointers (hyperlinks) to content on any Internet host.14

Định nghĩa. Một yêu cầu HTTP gồm một dòng yêu cầu (request line) dạng method URI version, theo sau là các dòng tiêu đề (request headers) và một dòng trống kết thúc. Một phản hồi HTTP gồm một dòng phản hồi dạng version status-code status-message, các tiêu đề, một dòng trống, rồi thân phản hồi.14

Nói đơn giản. Một yêu cầu web bắt đầu bằng một dòng kiểu “Lấy cho tôi trang này”, rồi vài dòng thông tin thêm. Phản hồi mở đầu bằng một mã như 200 OK rồi mới tới nội dung. Nhớ nhé: xin mở đầu bằng GET, đáp mở đầu bằng một mã số.

Definition. An HTTP request is a request line of the form method URI version, followed by request headers and a terminating empty line. An HTTP response is a response line of the form version status-code status-message, headers, an empty line, then the response body.14

GET / HTTP/1.1
Host: www.aol.com
→ HTTP/1.0 200 OK
  Content-Type: text/html
status: 200·301·400·403·404·501·505

khách: "GET / HTTP/1.1"
chủ: "200 OK" + nội dung

GET / HTTP/1.1
Host: www.aol.com
→ HTTP/1.0 200 OK
  Content-Type: text/html
status: 200·301·400·403·404·501·505

  1. HTTP

    HTTP — giao thức văn bản đơn giản, gõ tay được bằng telnet HTTP — ngôn ngữ chữ đơn giản của web HTTP — a simple text protocol you can type by hand

    Vì HTTP dựa trên các dòng văn bản truyền qua kết nối Internet, ta có thể dùng chương trình telnet để thực hiện giao dịch với bất kỳ máy chủ web nào.1 HTTP hỗ trợ nhiều phương thức — GET, POST, HEAD, PUT, DELETE… — nhưng sách chỉ bàn phương thức chủ lực GET, vốn chiếm đa số yêu cầu. Trong HTTP/1.1, tiêu đề Host là bắt buộc; mỗi dòng văn bản phải kết thúc bằng cặp xuống dòng về đầu (\r\n).14

    HTTP chỉ là những dòng chữ gửi qua lại, đơn giản tới mức bạn gõ tay cũng được. Lệnh hay dùng nhất là GET — nghĩa là “lấy cho tôi”. Nhớ nhé: GET là lệnh “lấy cho tôi trang này”.

    Because HTTP is based on text lines sent over an Internet connection, we can use the telnet program to conduct a transaction with any web server.1 HTTP supports several methods — GET, POST, HEAD, PUT, DELETE… — but the book covers only the workhorse GET, which accounts for most requests. In HTTP/1.1 the Host header is required; each text line must end with a carriage-return/line-feed pair (\r\n).14

    Bạn gặp nó ở đâuWhere you meet it Mã trạng thái (status code) là số nguyên ba chữ số báo kết quả: 200 OK, 301 chuyển vĩnh viễn, 400 yêu cầu sai, 403 cấm, 404 không tìm thấy, 501 chưa hỗ trợ, 505 không hỗ trợ phiên bản.1 Con số 404 quen thuộc chính là “không tìm thấy trang” — một mã trạng thái của HTTP. The status code is a three-digit integer reporting the outcome: 200 OK, 301 moved permanently, 400 bad request, 403 forbidden, 404 not found, 501 not implemented, 505 version not supported.1

    HTTP/1.1 so với HTTP/1.0

    HTTP/1.1 là phiên bản gần nhất mà sách bàn; HTTP/1.0 là bản cũ, đơn giản hơn nhiều, từ năm 1996. HTTP/1.1 thêm các tiêu đề hỗ trợ bộ nhớ đệm, bảo mật, và cơ chế cho nhiều giao dịch trên cùng một kết nối bền (persistent connection). Hai bản tương thích vì bên nào cũng bỏ qua tiêu đề lạ.14

    Proxy và tiêu đề Host

    Tiêu đề Host được các proxy cache dùng: nhiều proxy có thể nằm giữa trình duyệt và máy chủ gốc (origin server) thành một chuỗi proxy; dữ liệu trong Host giúp một proxy giữa chuỗi biết nó có thể có bản sao cục bộ của nội dung được yêu cầu hay không.1

  2. static + dynamic

    Nội dung tĩnh và động — đọc tệp, hay chạy chương trình Nội dung tĩnh và động — trang có sẵn, hay trang tự sinh Static & dynamic content — fetch a file, or run a program

    Với web, nội dung là một chuỗi byte kèm một kiểu MIME (MIME type) như text/html hay image/jpeg.1 Máy chủ cấp nội dung theo hai cách: lấy một tệp trên đĩa và trả về (nội dung tĩnh), hoặc chạy một tệp thực thi và trả về đầu ra của nó (nội dung động). Mỗi nội dung gắn với một URL (universal resource locator); ví dụ http://www.google.com:80/index.html định danh tệp /index.html trên host www.google.com phục vụ ở cổng 80.1

    Có hai loại trang: trang tĩnh là tệp có sẵn máy chủ cứ thế đưa; trang động là máy chủ chạy một chương trình rồi đưa kết quả. Mỗi thứ có một địa chỉ đầy đủ gọi là URL — chính là dòng chữ trên thanh địa chỉ trình duyệt. Nhớ nhé: tĩnh là lấy tệp có sẵn, động là chạy chương trình rồi đưa kết quả.

    To the web, content is a sequence of bytes with a MIME type such as text/html or image/jpeg.1 A server provides content two ways: fetch a disk file and return it (static content), or run an executable and return its output (dynamic content). Each piece of content has a URL (universal resource locator); e.g. http://www.google.com:80/index.html identifies the file /index.html on host www.google.com served on port 80.1

    Bạn gặp nó ở đâuWhere you meet it Nội dung động theo chuẩn CGI (common gateway interface): với URL /cgi-bin/adder?15000&213, máy chủ fork rồi execve chương trình, đặt biến môi trường QUERY_STRING là 15000&213, và chương trình trả về 15000 + 213 = 15213.1 Khi một trang hiện kết quả tính toán riêng cho bạn, máy chủ vừa chạy một chương trình nhỏ để sinh ra nó. Dynamic content follows the CGI (common gateway interface) standard: for the URL /cgi-bin/adder?15000&213, the server forks then execves the program, sets the QUERY_STRING environment variable to 15000&213, and the program returns 15000 + 213 = 15213.1

    Đầu ra của CGI đi đâu

    Chương trình CGI gửi nội dung động ra đầu ra chuẩn (standard output). Trước khi chạy, tiến trình con dùng dup2 để chuyển hướng đầu ra chuẩn tới bộ mô tả đã nối với khách — nên mọi thứ chương trình in ra đều đi thẳng tới trình duyệt.1

    Tham số GET so với POST

    Với GET, tham số nằm trong URI sau dấu ?, mỗi tham số ngăn bởi &, dấu cách phải mã hoá thành %20. Với POST, tham số nằm trong thân yêu cầu, và con đọc chúng từ đầu vào chuẩn.1

  3. Tiny web server

    Máy chủ TINY — 250 dòng gói trọn cả chương Máy chủ TINY — một máy chủ web tí hon tự tay viết The TINY server — 250 lines that tie the chapter together

    Chương khép lại bằng TINY, một máy chủ web nhỏ nhưng hoạt động được, kết hợp nhiều ý tưởng đã học — điều khiển tiến trình, Unix I/O, giao diện ổ cắm và HTTP — trong chỉ khoảng 250 dòng mã.1 TINY là một máy chủ lặp (iterative server): sau khi mở socket nghe bằng open_listenfd, nó chạy vòng lặp vô hạn — accept một yêu cầu kết nối, thực hiện một giao dịch, rồi đóng đầu kết nối của mình.1

    Cuối chương, tác giả tự viết một máy chủ web tí hon tên TINY chỉ khoảng 250 dòng, nhưng chạy được với trình duyệt thật và phục vụ cả trang tĩnh lẫn động. Nó cứ lặp: chờ khách, phục vụ, rồi gác máy. Nhớ nhé: một máy chủ web thật chỉ cần 250 dòng để nên hình.

    The chapter closes with TINY, a small but functioning web server that combines many learned ideas — process control, Unix I/O, the sockets interface, and HTTP — in only about 250 lines of code.1 TINY is an iterative server: after opening a listening socket with open_listenfd, it runs an infinite loop — accept a connection request, perform one transaction, then close its end of the connection.1

    Bạn gặp nó ở đâuWhere you meet it TINY chỉ hỗ trợ phương thức GET và nói HTTP/1.0; hàm doit đọc và phân tích dòng yêu cầu, rồi phục vụ nội dung tĩnh hoặc động — đủ để trỏ một trình duyệt thật vào và thấy nó hiện trang có cả chữ lẫn hình.1 Chính các tác giả cũng thấy “hồi hộp” khi trỏ trình duyệt thật vào máy chủ tự viết và thấy nó chạy. TINY supports only GET and speaks HTTP/1.0; its doit function reads and parses the request line, then serves static or dynamic content — enough to point a real browser at it and watch it display a page with text and graphics.1

    Vì sao dùng Rio chứ không phải I/O chuẩn

    Trên socket mạng, thư viện I/O chuẩn vướng các hạn chế khó chịu (cấm xen kẽ đọc–ghi nếu không gọi fflush/fseek, và cấm lseek trên socket). Vì thế các tác giả khuyên dùng các hàm Rio bền vững của sách cho I/O trên socket.1

    World Wide Web ra đời

    Web do Tim Berners-Lee phát minh khi làm việc tại CERN: năm 1989 ông viết bản ghi nhớ nội bộ đề xuất một hệ siêu văn bản phân tán; trình duyệt đồ hoạ mosaic năm 1993 của Marc Andreessen tại NCSA khiến web bùng nổ. Sách dẫn: tới 2015 có hơn 975.000.000 website.18

Ba ngộ nhận thường gặp Three common misconceptions

“Khách và chủ là hai cái máy khác nhau” “A client and server are two different machines”

Ngộ nhận: client là một máy, server là một máy khác.

Thực tế: khách và chủ là các tiến trình, không phải máy; một host có thể chạy nhiều khách và chủ cùng lúc, kể cả trên cùng một máy.1

Myth: the client is one machine, the server another.

Reality: clients and servers are processes, not machines; a host can run many clients and servers at once, even on the same machine.1

“IP tự nó bảo đảm dữ liệu đến nơi an toàn” “IP by itself guarantees reliable delivery”

Ngộ nhận: cứ gửi qua IP là chắc chắn tới nơi, đúng thứ tự.

Thực tế: IP là cơ chế không đáng tin cậy, không khôi phục khi gói mất; chính TCP xây trên IP mới cho kết nối đáng tin cậy. Đừng nhầm hai tầng.12

Myth: anything sent over IP surely arrives, in order.

Reality: IP is an unreliable mechanism that does not recover lost packets; it is TCP, built on IP, that provides reliable connections. Don't conflate the two layers.12

“HTTP là một giao thức nhị phân phức tạp” “HTTP is a complex binary protocol”

Ngộ nhận: HTTP khó, phải có thư viện riêng mới dùng được.

Thực tế: HTTP dựa trên các dòng văn bản đơn giản tới mức bạn có thể dùng telnet gõ tay một yêu cầu và đọc được phản hồi.1

Myth: HTTP is hard and needs a special library.

Reality: HTTP is based on text lines simple enough that you can type a request by hand with telnet and read the response.1

Tự kiểm Self-check

Năm câu hỏi để biết bạn đã nắm lập trình mạng Năm câu hỏi kiểm tra nhanh Five questions to check you grasped network programming

Trả lời được những câu này nghĩa là bạn đã đi trọn hành trình từ mô hình khách-chủ, qua ổ cắm và Internet IP, tới HTTP và máy chủ web.

Nếu trả lời được, nghĩa là bạn đã hiểu chương này.

Answering these means you walked the whole path from the client-server model, through sockets and the IP Internet, to HTTP and the web server.

  1. Bốn bước của một giao dịch khách-chủ là gì? Vì sao nói khách và chủ là tiến trình chứ không phải máy?

    Gợi ý sâu hơn: một host có thể đồng thời đóng cả hai vai trong những cuộc trao đổi khác nhau không?

  2. “Đóng gói (encapsulation)” nghĩa là gì, và vì sao nó là chìa khoá để các mạng không tương thích nói chuyện được?

    Gợi ý sâu hơn: khi một gói đi qua router từ LAN1 sang LAN2, header nào bị tháo và header nào được gắn mới?

  3. Một địa chỉ socket gồm những gì? Cặp socket (socket pair) xác định điều gì, và “cổng quen thuộc” của web là số mấy?

    Gợi ý sâu hơn: vì sao cổng của khách là cổng tạm còn cổng của chủ lại cố định?

  4. Phân biệt vai trò của bind, listen, accept (phía chủ) với connect (phía khách). Bộ mô tả nghe khác bộ mô tả đã nối ra sao?

    Gợi ý sâu hơn: sự phân biệt hai loại bộ mô tả giúp dựng loại máy chủ nào ở Chương 12?

  5. Một yêu cầu và một phản hồi HTTP có cấu trúc thế nào? Phân biệt nội dung tĩnh và nội dung động, và cho biết CGI dùng để làm gì.

    Gợi ý sâu hơn: với URL /cgi-bin/adder?15000&213, máy chủ truyền tham số cho tiến trình con bằng cách nào?

  1. Trên mạng, bên nào hỏi và bên nào đáp? Kể bốn bước của cuộc trao đổi.

  2. Vì sao phải “bọc” dữ liệu thành gói có địa chỉ chung khi đi qua nhiều mạng?

  3. Địa chỉ IP là gì, và vì sao người ta còn đặt thêm tên (như google.com)?

  4. Để nối hai chương trình qua mạng, khách làm gì và chủ làm gì?

  5. Web dùng “ngôn ngữ” nào? Lệnh GET và mã 404 nghĩa là gì?

  1. What are the four steps of a client-server transaction? Why are clients and servers processes, not machines?

  2. What does encapsulation mean, and why is it the key to bridging incompatible networks?

  3. What makes up a socket address? What does a socket pair identify, and what is the web's well-known port?

  4. Distinguish bind, listen, accept (server) from connect (client). How does a listening descriptor differ from a connected one?

  5. How are an HTTP request and response structured? Distinguish static from dynamic content, and say what CGI is for.

Khép lại chương Closing the chapter

Mọi ứng dụng mạng đều quy về một mô hình khách-chủ chạy trên Internet IP toàn cầu; lập trình viên nối hai tiến trình qua giao diện ổ cắm, rồi trên nền ấy dựng nên HTTP và cả một máy chủ web hoạt động được.1

Trên mạng luôn có một bên hỏi và một bên đáp; người lập trình chỉ cần một ổ cắm để nối chúng lại và một ngôn ngữ chung như HTTP là dựng được cả một trang web. Nhớ nhé: khách–chủ, ổ cắm, HTTP — ba mảnh ghép làm nên web.

Every network application reduces to a client-server model running over the global IP Internet; the programmer joins two processes through the sockets interface, and on that foundation builds HTTP and a working web server.1