A zero-dependency cookbook for beginners. Everything below uses only the Python 3 standard library (socket, select, struct, hashlib, zlib, json, sys), flat procedural code, no asyncio, threads, or classes. Every script prints connections, messages and state changes so you can watch the protocol work. Run servers and clients in separate terminal tabs with python3 script.py <args>.

Part 1: Core Concepts & Standard Library Rules

  • What a Socket Is: An Operating System endpoint that sends and receives raw bytes over a network.
  • IP vs. Port: The IP address ('localhost' or '127.0.0.1') identifies the machine; the Port (an integer like 10000) identifies the specific Python process.
  • Networks Only Speak Bytes (b"..."): Convert str to bytes before sending with .encode(), and convert received bytes back to str with .decode().
  • TCP (SOCK_STREAM) vs. UDP (SOCK_DGRAM):
    • TCP is connection-oriented (bind -> listen -> accept on server; connect -> sendall -> recv on client).
    • UDP is connectionless (sendto and recvfrom). A UDP server uses a single socket for all clients and never uses select.select().
  • Socket Port Reuse (SO_REUSEADDR): Always add server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) before bind() on TCP servers and proxies to avoid Address already in use errors when restarting.
  • Binary Struct Packing (struct.Struct):
    • Format codes: i (4-byte int), I (4-byte unsigned int), f (4-byte float), ? (1-byte bool), c or 1s (1-byte char as bytes), Xs like 7s (X-byte string as bytes).
    • C Alignment Padding Rule: Never count bytes manually ('c i' is 8 bytes due to 3 padding bytes; 'i c' is 5 bytes; 'i i c' is 9 bytes; 'I I 1s' is 12 bytes; '7s6s' is 13 bytes). Always pass packer.size to recv(packer.size).
    • Null-Byte Padding Rule: Packing a shorter string like b"FAIL" into a 7s field pads the trailing bytes with null bytes (b"FAIL\x00\x00\x00"). Always strip null bytes after unpacking: status = status_bytes.decode().strip('\x00').

Part 2: Essential Building Blocks

import sys, struct, json, hashlib, zlib # 1. Command-Line Arguments (python3 script.py localhost 10000 input.txt) ip = sys.argv[1] port = int(sys.argv[2]) filename = sys.argv[3] # 2. Struct Packing & Unpacking packer = struct.Struct('i i 1s') packed_bytes = packer.pack(10, 25, b'+') a, b, raw_op = packer.unpack(packed_bytes) op = raw_op.decode().strip('\x00') # 3. Delimiter-Separated Payloads (':', ';', '|') numbers = [3, 7, 12, 18, 20] bet = 500 msg_bytes = (":".join(str(x) for x in numbers) + f":{bet}").encode() parts = [int(x) for x in msg_bytes.decode().split(":")] recv_nums, recv_bet = parts[:-1], parts[-1] # 4. Reading Text, JSON, and Binary Files with open("input.json", "r") as f: data = json.load(f) # 5. MD5 and CRC32 Checksums md5_hex = hashlib.md5(b"1:5:12:19:20").hexdigest() crc_int = zlib.crc32(b"1:5:12:19:20") 

Part 3: Master Network Templates (TCP, Select, UDP, TCP-UDP Proxy)

Template 1: Single-Client TCP Server & Client

# --- tcp_server.py --- import socket, sys ip, port = sys.argv[1], int(sys.argv[2]) with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as server: server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) server.bind((ip, port)) server.listen(5) print(f"TCP Server listening on {ip}:{port}") while True: conn, addr = server.accept() with conn: print(f"Connected by {addr}") data = conn.recv(1024) if data: print("Received:", data.decode()) conn.sendall(b"Hello client") 
# --- tcp_client.py --- import socket, sys ip, port = sys.argv[1], int(sys.argv[2]) with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as client: client.connect((ip, port)) client.sendall(b"Hello server") print("Server replied:", client.recv(1024).decode()) 

Template 2: Multi-Client TCP Server with select.select()

# --- select_tcp_server.py --- import socket, select, sys ip, port = sys.argv[1], int(sys.argv[2]) server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) server.bind((ip, port)) server.listen(5) inputs = [server] print(f"Multi-client TCP Server running on {ip}:{port}...") while True: readable, _, _ = select.select(inputs, [], [], 1.0) for s in readable: if s is server: conn, addr = server.accept() print(f"[+] New client connected: {addr}") inputs.append(conn) else: data = s.recv(1024) if not data: print("[-] Client disconnected") inputs.remove(s) s.close() else: print(f"[<] Received: {data.decode()}") s.sendall(b"OK") 

Template 3: UDP Server & Client with Timeout

# --- udp_server.py --- import socket, sys sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.bind((sys.argv[1], int(sys.argv[2]))) while True: data, client_addr = sock.recvfrom(1024) print(f"Received {data.decode()} from {client_addr}") sock.sendto(b"Hello Client", client_addr) 
# --- udp_client.py --- import socket, sys server_addr = (sys.argv[1], int(sys.argv[2])) sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.settimeout(2.0) try: sock.sendto(b"Hello Server", server_addr) data, _ = sock.recvfrom(1024) print("Received:", data.decode()) except (socket.timeout, ConnectionResetError): print("UDP Server did not respond!") finally: sock.close() 

Template 4: TCP-to-UDP Bridge Proxy

# --- tcp_udp_proxy.py --- # Usage: python3 tcp_udp_proxy.py <proxy_ip> <proxy_port> <server_ip> <server_port> import socket, select, struct, sys proxy_addr = (sys.argv[1], int(sys.argv[2])) server_addr = (sys.argv[3], int(sys.argv[4])) tcp_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) tcp_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) tcp_sock.bind(proxy_addr) tcp_sock.listen(5) udp_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) udp_sock.settimeout(2.0) packer = struct.Struct("i i c") inputs = [tcp_sock] while True: readable, _, _ = select.select(inputs, [], []) for s in readable: if s is tcp_sock: conn, addr = tcp_sock.accept() print("Client connected to proxy:", addr) inputs.append(conn) else: msg = s.recv(packer.size) if not msg: inputs.remove(s) s.close() continue udp_sock.sendto(msg, server_addr) result, _ = udp_sock.recvfrom(packer.size) val, zero, r_char = packer.unpack(result) s.sendall(packer.pack(val * 2, zero, r_char)) 

Part 4: 5 Complete Protocol Implementations

Implementation 1: Schedule & Seat Reservation Protocol (7s6s) + 50% Intercept Proxy

Sample screenings.txt:

Dune;Hall 1;17:30;5 Oppenheimer;Hall 2;19:00;3 Barbie;Hall 1;20:45;0 
# --- reservation_server.py --- # Usage: python3 reservation_server.py <ip> <port> <screenings.txt> import socket, select, struct, sys, random, string ip, port, filename = sys.argv[1], int(sys.argv[2]), sys.argv[3] screenings = {} with open(filename, "r") as f: for line in f: line = line.strip() if line: title, hall, start_time, seats = line.split(";") screenings[f"{title};{start_time}"] = { "title": title, "hall": hall, "time": start_time, "seats": int(seats) } packer = struct.Struct("7s6s") server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) server.bind((ip, port)) server.listen(5) inputs = [server] print(f"Server running on {ip}:{port}...") while True: readable, _, _ = select.select(inputs, [], []) for s in readable: if s is server: conn, addr = server.accept() print(f"[+] Client connected: {addr}") inputs.append(conn) else: data = s.recv(1024) if not data: print("[-] Client disconnected") inputs.remove(s) s.close() continue msg = data.decode().strip() print(f"[<] Received: {msg}") if msg == "GET_SCREENINGS": reply_str = "|".join( f"{v['title']};{v['hall']};{v['time']}" for v in screenings.values() ) s.sendall(reply_str.encode()) print(f"[>] Sent screenings: {reply_str}") else: if msg in screenings and screenings[msg]["seats"] > 0: screenings[msg]["seats"] -= 1 ticket_id = "".join(random.choices(string.ascii_uppercase + string.digits, k=6)) s.sendall(packer.pack(b"SUCCESS", ticket_id.encode())) print(f"[>] SUCCESS for {msg}. ID: {ticket_id} (Seats left: {screenings[msg]['seats']})") else: s.sendall(packer.pack(b"FAIL", b"000000")) print(f"[>] FAIL for {msg}.") 
# --- reservation_client.py --- # Usage: python3 reservation_client.py <ip> <port> <film_title> <start_time> import socket, struct, sys ip, port = sys.argv[1], int(sys.argv[2]) film = sys.argv[3] if len(sys.argv) > 3 else "Dune" time_str = sys.argv[4] if len(sys.argv) > 4 else "17:30" packer = struct.Struct("7s6s") with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as client: client.connect((ip, port)) client.sendall(b"GET_SCREENINGS") print("[>] Sent: GET_SCREENINGS") screenings_raw = client.recv(1024).decode() print("[<] Available screenings:") for item in screenings_raw.split("|"): print(" -", item) buy_req = f"{film};{time_str}" client.sendall(buy_req.encode()) print(f"[>] Attempting to reserve: {buy_req}") resp_data = client.recv(packer.size) status_bytes, ticket_bytes = packer.unpack(resp_data) status = status_bytes.decode().strip('\x00') ticket_id = ticket_bytes.decode().strip('\x00') print(f"[<] Server Result: {status}, Ticket ID: {ticket_id}") 
# --- intercept_proxy.py --- # Usage: python3 intercept_proxy.py <proxy_ip> <proxy_port> <server_ip> <server_port> import socket, struct, sys, random proxy_addr = (sys.argv[1], int(sys.argv[2])) server_addr = (sys.argv[3], int(sys.argv[4])Source:https://dev.to/unnobatroo/python-3-standard-library-socket-programming-cookbook-tcp-udp-selectselect-struct-packing-4hjj

Related posts