Socket Programming Basics
A socket does not necessarily deliver the complete HTTP response in one piece.
Try it: Reading a Socket in Chunks
How the Python for Everybody socket client reads a web document: it sends a raw HTTP GET, then calls recv(n) in a loop, getting pieces of whatever has arrived, until an empty result says the server closed; the headers end at the first blank line (\r\n\r\n).
How it works
- Connect a socket to the server on port 80 and send 'GET http://host/path HTTP/1.0' followed by an empty line.
- Call recv(n): it returns at most n bytes — only what is waiting in the socket buffer — and blocks while nothing has arrived yet.
- Append each chunk to data; the chunk sizes depend on the buffer size and on packet timing.
- When recv returns b'' the server has closed the connection, so break out of the loop.
- Find the first b'\r\n\r\n': before it are the status line and headers, after it is the document (Content-Length bytes).
Default run (19 steps): The client will fetch http://data.pr4e.org/romeo.txt with a raw socket and read the reply 64 bytes at a time. The server's reply is 335 bytes and will arrive in 4 packets of up to 100 bytes. … Split: data[:164] is the status line and headers; data[164+4:] is the 167-byte body — the document itself (its Content-Length says 167).
Simplified: The network is a model on a simulated clock: the reply arrives in equal-size packets at a fixed interval and the server closes with the last packet. The response headers are a fixed template. Nothing is sent over a real network.
Loading the simulation…
From Socket to Saved Image
Retrieving an image over HTTP is a movement of bytes through several stages. A program connects to a server, sends an HTTP GET request, receives the response in chunks, combines those chunks into one bytes buffer, removes the HTTP headers, and writes the remaining binary body to a file. The essential discipline is to keep the response as bytes from the moment it arrives until it is written to disk.
The Three-Stage Retrieval Pattern
- 1Establish a socket connection and send an HTTP GET request for the binary file.
- 2Receive response chunks and concatenate them into an initially empty bytes buffer until the server closes the connection.
- 3Find the double CRLF boundary, extract the bytes after it, and write those bytes to a file opened in binary write mode.
Accumulating Response Chunks
A socket does not necessarily deliver the complete HTTP response in one piece. The program receives data in chunks, typically 5120 bytes at a time, and adds each chunk to a growing buffer. The buffer begins as an empty bytes object, represented by b"". Each received chunk is concatenated to the existing buffer. This continues until the receive operation returns fewer than 1 byte, indicating that the server has closed the connection and no more data is available.
Finding the Header Boundary
After the socket closes, the buffer contains two different parts: the HTTP response headers and the binary image body. HTTP separates these parts with a blank line represented by two consecutive carriage return and line feed sequences: \r\n\r\n. Search the bytes buffer for this exact marker with find(b'\r\n\r\n'). The find operation returns the index where the marker begins. Because the marker occupies 4 bytes, the body begins at position pos + 4. Slicing from that position onward discards the headers and keeps only the image bytes.
Separating One HTTP Response
A complete response buffer contains HTTP headers, the marker \r\n\r\n, and an image body. How should the program identify the bytes to save?
- 1Locate the marker
Search the bytes buffer with
find(b'\r\n\r\n'). The returned position is the start of the four-byte separator. - 2Move past the separator
Add 4 to the returned position because the double CRLF marker is four bytes long.
- 3Extract the body
Slice the buffer from position + 4 onward. The resulting bytes contain the binary image body without the HTTP headers.
The saved data must be the response buffer sliced from the first byte after the double CRLF marker through the end of the buffer.
Writing Bytes Without Corruption
Once the body has been extracted, open the destination file in binary write mode, written as wb, and write the binary data to it. Binary write mode avoids encoding transformations that can corrupt the received data. The HTTP headers should not be written to the file; only the bytes after the double CRLF marker belong in the image file.
Check the Content-Type header before saving the body. Values such as image/jpeg or image/png indicate an image response. If the server instead returns text/html, the request may have gone wrong, and saving the response as an image would be inappropriate.
Common Retrieval Mistakes
Common mistake Initializing the response buffer as text instead of bytes.
What it looks likeUsing an empty string for data that will contain an image response.
Why it failsBinary response data must be accumulated in a bytes buffer, not handled as text.
Do this insteadStart with an empty bytes object, represented by b"".
Common mistake Saving the complete response buffer.
What it looks likeWriting the headers and the image body together to the output file.
Why it failsThe file begins with HTTP metadata rather than only the binary image body.
Do this insteadFind the double CRLF marker and write only the slice beginning at position + 4.
Common mistake Skipping the wrong number of bytes after the marker.
What it looks likeStarting the body slice at pos or pos + 2.
Why it failsThe double CRLF marker is four bytes long.
Do this insteadBegin the body slice at pos + 4.
Common mistake Hard-coding the header length.
What it looks likeAlways removing a fixed number of bytes before saving.
Why it failsThe header-body boundary should be located by searching for the marker.
Do this insteadUse find(b'\r\n\r\n') to determine the boundary.Common mistake Opening the destination in text mode.
What it looks likeWriting image data with a text-oriented file mode.
Why it failsEncoding transformations can corrupt binary data.
Do this insteadUse binary write mode, wb.
Trace the Complete Process
Describe the path of an image response in your own words. Include what the initial buffer contains, what happens to each received chunk, how the header-body boundary is found, which bytes are discarded, and which file mode is used for the final write.
Hints
- The response buffer eventually contains both headers and body.
- The boundary marker is the byte pattern \r\n\r\n.
- The marker is four bytes long, so the body begins at position + 4.
- The destination must be opened in binary write mode.
| Stage | Data held | Action |
|---|---|---|
| Receive | Incoming response chunks | Concatenate each chunk to the bytes buffer |
| Separate | Headers followed by binary body | Find the double CRLF marker and skip four bytes |
| Save | Binary body only | Write it to a file in wb mode |
| Verify | HTTP metadata | Check Content-Type before saving |
The state of the data at each major stage
Key Takeaways
- 1Accumulate socket data in a bytes buffer initialized as b"".
- 2Continue receiving and concatenating chunks until the server closes the connection.
- 3Find the HTTP header-body boundary with
find(b'\r\n\r\n'). - 4Because the marker is four bytes long, extract the body from position + 4 onward.
- 5Write only the binary body to a file opened in binary write mode, wb, and check Content-Type when verifying the response.
At a glance
- A complete HTTP response contains headers followed by a binary body.
- Socket data arrives in chunks, so the chunks must be concatenated into a growing bytes buffer.
- The double CRLF marker, \r\n\r\n, separates the headers from the body.
- The binary body begins four bytes after the marker and should be written using binary write mode, wb.
- Checking Content-Type helps confirm that the response is the expected image rather than an error page.