socket.recv reads up to a specified number of bytes from a socket. Because socket input may arrive in pieces, applications usually call recv repeatedly and buffer the results until a message boundary appears. section 3.2.1
Use recv with these practical rules:
- Pass an integer byte limit, such as 2 for a deliberately small demonstration buffer or 1024 for a more practical application buffer. section 3.2.1
- Append each returned byte string to a buffer and stop when the protocol delimiter, such as carriage return plus line feed, is present. section 3.2.1
- Remember that blocking sockets make recv wait for data, potentially preventing other clients from being processed. section 3.2.2
Read a Telnet line in pieces
A server can repeatedly call connection.recv(2), append each result to buffer, and stop when buffer ends with b'\r\n'. Sending testing123 through Telnet produces chunks such as b'te', b'st', and b'\r\n', which combine into b'testing123\r\n'.
Listing 3.7 Using selectors to build a non-blocking server
import selectors
import socket
from selectors import SelectorKey
from typing import List, Tuple
selector = selectors.DefaultSelector()
server_socket = socket.socket()
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_address = ('127.0.0.1', 8000)
server_socket.setblocking(False)
server_socket.bind(server_address)
server_socket.listen()
selector.register(server_socket, selectors.EVENT_READ)
while True:
events: List[Tuple[SelectorKey, int]] = selector.select(timeout=1) #1
if len(events) == 0: #2
print('No events, waiting a bit more!')
for event, _ in events:
event_socket = event.fileobj #3
if event_socket == server_socket: #4
connection, address = server_socket.accept()
connection.setblocking(False)
print(f"I got a connection from {address}")
selector.register(connection, selectors.EVENT_READ) #5
else:
data = event_socket.recv(1024) #6
print(f"I got some data: {data}")
event_socket.send(data)
Inspect a selectors-based echo server that calls socket.recv only after the operating system reports a read event, avoiding blocking while serving multiple clients. section 3.4
