Chapter 35 Exercises: Networking and Internet Programming
Part A: Conceptual Understanding
A.1. Explain the difference between TCP and UDP. Give two real-world applications that use TCP and two that use UDP, and explain why each choice is appropriate.
Guidance
TCP is reliable, ordered, and connection-oriented — data is guaranteed to arrive in order. UDP is unreliable, connectionless, and does not guarantee delivery. TCP applications: web browsing (HTTP), email (SMTP) — correctness matters more than speed. UDP applications: video streaming (a dropped frame is better than a delayed one), DNS lookups (single packet, fast response needed). The key trade-off is reliability vs. latency.A.2. What is a port number? Why can a single server machine run multiple network services (web server, email server, database server) simultaneously?
Guidance
A port number is a 16-bit integer (0-65535) that identifies a specific service on a machine. When a client connects to a server, it specifies both the IP address (which machine) and the port (which service on that machine). A single machine can run a web server on port 80, an email server on port 25, and a database on port 5432 simultaneously because each service listens on a different port. The operating system routes incoming packets to the correct service based on the destination port.A.3. Describe the HTTP request-response cycle. What are the four parts of an HTTP request? What are the three parts of an HTTP response?
Guidance
Cycle: Client sends a request, server processes it, server sends a response. HTTP request parts: (1) Request line (method, path, version), (2) Headers (key-value pairs), (3) Blank line separator, (4) Optional body. HTTP response parts: (1) Status line (version, status code, reason phrase), (2) Headers, (3) Body. The blank line between headers and body is mandatory in both directions.A.4. What is REST? How does it differ from a raw TCP protocol? Why has REST become the dominant API style?
Guidance
REST (Representational State Transfer) is an architectural style for web APIs that uses HTTP methods (GET, POST, PUT, DELETE) on URL-identified resources. It differs from raw TCP in that it uses an existing, well-understood protocol (HTTP), standard data formats (JSON), and stateless communication. REST became dominant because: it leverages existing web infrastructure, it is simple to understand and implement, it works with any language that has an HTTP library, and it scales well because of its stateless nature.A.5. Why does MicroServe set Connection: close in its response headers? What would happen if it did not?
Guidance
`Connection: close` tells the client that the server will close the connection after sending the response. Without it, HTTP/1.1 defaults to `Connection: keep-alive`, meaning the client expects the connection to remain open for additional requests. Since MicroServe's simple implementation reads one request per connection, leaving the connection open would cause the client to wait indefinitely for a response that will never come (the server has moved on to the next connection). Production servers support keep-alive for performance, but it adds complexity.Part B: Applied Analysis
B.1. You are designing a REST API for a library catalog system. Design the URL structure and HTTP methods for: listing all books, getting a specific book, adding a new book, updating a book, deleting a book, and searching books by title. For each endpoint, specify the HTTP method, URL, request body (if any), and expected response.
Guidance
GET /api/books → 200 + JSON array of all books. GET /api/books/42 → 200 + JSON object for book 42 (or 404). POST /api/books + JSON body → 201 + created book with ID. PUT /api/books/42 + JSON body → 200 + updated book (or 404). DELETE /api/books/42 → 204 No Content (or 404). GET /api/books?title=pascal → 200 + JSON array of matching books. This follows REST conventions: nouns in URLs, verbs in HTTP methods, plural resource names.B.2. Compare the error handling strategies for file I/O (Chapter 13) and network I/O (this chapter). What additional failure modes does network I/O introduce? How should your error handling differ?
Guidance
File I/O failures: file not found, permission denied, disk full, corrupt data. Network I/O adds: connection refused (server down), timeout (server slow), DNS resolution failure (hostname unknown), connection reset (server crashed mid-transfer), partial data (network interrupted), SSL/TLS errors. Network error handling must include timeouts, retry logic (with backoff), graceful degradation (work offline), and user-visible status indicators. File I/O errors are usually fatal; network errors are often transient and worth retrying.Part C: Code Exercises
C.1. Write a program that uses TFPHTTPClient to fetch a JSON response from a public API (e.g., http://httpbin.org/get), parse the response, and display specific fields. Handle connection errors gracefully.
Guidance
Create a TFPHTTPClient, call Get() on the URL, parse the response with GetJSON(), extract fields with TJSONObject.Get(). Wrap everything in try-except for EHTTPClient and ESocketError. Display the status code, content type from response headers, and parsed JSON fields.C.2. Build a simple "time server" and "time client" using TCP sockets. The server listens on port 7777, and when a client connects, it sends the current date and time as a formatted string and closes the connection. The client connects, reads the time, and displays it.
Guidance
Server: Create TInetServer on port 7777, set OnConnect handler. In the handler, format the current time as a string, write it to the TSocketStream, done. Client: Create TInetSocket to localhost:7777, read from the socket into a buffer, convert to string, display. Keep it simple — this is a one-shot protocol (connect, receive, disconnect).C.3. Extend MicroServe with three new routes: GET /api/time (returns current time as JSON), GET /api/echo?msg=hello (returns the query parameter as JSON), and POST /api/reverse (takes a JSON body with a "text" field and returns the reversed text). Test each route using TFPHTTPClient from a separate test program.
Guidance
For /api/time, create a JSON object with the current time and return it. For /api/echo, parse the query string from the path (split on '?', then split on '='). For /api/reverse, parse the request body as JSON, extract the "text" field, reverse it, return as JSON. The test program makes HTTP requests to each endpoint and displays the responses.C.4. Write a program that downloads a file from a URL and saves it to disk, displaying progress. Use TFPHTTPClient and its OnDataReceived event to track bytes received.
Guidance
Create TFPHTTPClient, assign an OnDataReceived handler that tracks total bytes and prints progress. Use Get() with a TFileStream as the output destination. Handle errors (404, timeout, network failure). Display final file size and download speed.Part D: Challenge Problems
D.1. Extend MicroServe into a complete expense API server that stores expenses in memory (using a dynamic array). Implement all four CRUD operations: GET /api/expenses (list all), POST /api/expenses (create), PUT /api/expenses/:id (update), DELETE /api/expenses/:id (delete). Handle invalid JSON, missing fields, and non-existent IDs with appropriate HTTP status codes.
Guidance
Store expenses in a global TExpenseArray. For path parameters (:id), extract the ID by parsing the path string. POST validates the JSON body and returns 201 with the created expense. PUT finds the expense by ID and updates it (or returns 404). DELETE removes the expense (or returns 404). GET returns the full array as a JSON array. This is a complete RESTful CRUD API.D.2. Build a simple HTTP proxy server. The proxy listens on port 9090, receives HTTP requests from a client, forwards them to the target server, receives the response, and sends it back to the client. Log every request (method, path, status code). This teaches you how HTTP proxies, load balancers, and API gateways work.