A socket read can return fewer bytes than requested; a framed receiver must loop until complete or EOF.
Make this comfortable
Python socket recv: assemble an exact frame across local socket reads
Operation contract
Two owned sockets exchange one complete seven-byte receipt frame, followed by a second frame whose body stops after three of seven bytes. The receiving loop collects exact lengths and rejects the truncated second frame when the sender closes its write side. No port or external host is used.
Failure boundary
socketpair checks one local stream on the tested host. A live network peer may stall without closing, so a receiver needs a deadline and an overall byte budget. This fixture does not prove TLS authentication, remote ordering, or operation under every socket platform.
Working program
import socket
def receive_exact(connection, byte_count):
chunks = []
remaining = byte_count
while remaining:
chunk = connection.recv(remaining)
if not chunk:
raise EOFError("receipt frame ended early")
chunks.append(chunk)
remaining -= len(chunk)
return b"".join(chunks)
def receive_frame(connection, maximum_body):
body_size = int.from_bytes(receive_exact(connection, 2), "big")
if body_size > maximum_body:
raise ValueError("receipt body too large")
return receive_exact(connection, body_size)
sender, receiver = socket.socketpair()
try:
receiver.settimeout(1)
sender.sendall((7).to_bytes(2, "big") + b"R47paid"
+ (7).to_bytes(2, "big") + b"R73")
sender.shutdown(socket.SHUT_WR)
print("first", receive_frame(receiver, 8).decode("ascii"))
try:
receive_frame(receiver, 8)
except EOFError:
print("short_second_rejected", True)
finally:
sender.close()
receiver.close()Output
first R47paid
short_second_rejected TrueCosts and limits
The loop copies each chunk into a list and joins at completion, using memory proportional to the bounded body. For large frames, stream into an owned sink under a separate total-byte policy.
Common Mistakes
- One recv call is not an exact-length contract.
- EOF before the declared body ends is a rejected frame.
- A socket timeout is not a total request deadline across many reads.
Connected lessons
python
socketpair-exact-recv
