Worked examples — Socket programming — TCP server - client, UDP server - client in Python
4.3.28 · D3· Coding › Computer Networks › Socket programming — TCP server - client, UDP server - clien
Tumne parent note mein calls already dekh li hain the parent note. Ab hum unhe stress-test karenge: "do programs ek socket pe baat karein to actually kya ho sakta hai" ke har quadrant ko. Loss, reordering, partial reads, closed peers, wrong protocol — har ek ka apna worked example hai taaki tum koi aisa case kabhi na dekho jise tumne pehle na dekha ho.
The scenario matrix
Neeche har worked example us cell ke saath tagged hai jise woh cover karta hai. Pehle table padho — yeh poora test surface hai.
| # | Cell (case class) | Protocol | Yahan kya alag hai | Example |
|---|---|---|---|---|
| A | Happy path, one send = one recv | TCP | Baseline, kuch bhi weird nahi | Ex 1 |
| B | Coalescing — bahut saare sends, ek recv | TCP | Stream mein koi message boundaries nahi | Ex 2 |
| C | Splitting — ek send, bahut saare recvs | TCP | Ek bada send pieces mein aata hai | Ex 3 |
| D | Peer closed — recv returns b'' |
TCP | Degenerate/EOF input | Ex 4 |
| E | Boundaries preserved | UDP | Ek sendto = ek recvfrom |
Ex 5 |
| F | Loss + reorder — the ugly case | UDP | Packets gayab ho jaate hain / ulte-seedhe aate hain | Ex 6 |
| G | Framing fix (length prefix) | TCP | Real-world word problem | Ex 7 |
| H | Wrong protocol / exam twist | mixed | listen on UDP, str not bytes, no bind |
Ex 8 |
Cells A–D TCP ke behaviour ko exhaust karte hain, E–F UDP ke, G standard fix dikhata hai, H exam trap collection hai. Saath mein yeh matrix ko cover karte hain.

Example 1 — Cell A: the happy path (TCP)
- Client OS ko 5 bytes deta hai.
Yeh step kyun?
b"hello"ASCII bytesh e l l o= 5 bytes hai.sendallinternally loop karta hai jab tak saare 5 bytes network ke liye queue nahi ho jaate. - Server "up to 1024" maangta hai.
Yeh step kyun?
recv(1024)matlab hai "jo bhi ready ho woh de do, zyada se zyada 1024 bytes". Kyunki sirf 5 bytes in flight hain aur woh saath aate hain, yeh saare 5 return karta hai. - Result:
data == b"hello",len(data) == 5.
Example 2 — Cell B: coalescing (TCP)
- TCP ek byte stream hai, message queue nahi.
Yeh step kyun? Kernel ko allowed hai ki outgoing bytes ko jaane se pehle ek segment mein merge kare.
"AA"aur"BB"ke beech koi marker nahi hai. - Server ka ek
recv(1024)jo bhi available hai woh sab scoop kar leta hai. Yeh step kyun? Jabrecvrun hota hai tab saare 6 bytes already receive buffer mein baithe ho sakte hain, to yeh unhe saath return kar deta hai. - Result: ek possible (localhost pe bahut common) outcome hai
data == b"AABBCC",len == 6.

Example 3 — Cell C: splitting (TCP)
recv(1024)kabhi bhi 1024 bytes se zyada return nahi kar sakta. Yeh step kyun? Humne max 1024 maanga. 3000 bytes ek call mein nahi aa sakte.- Har call up to 1024 return karta hai, jo bhi currently buffered hai.
Yeh step kyun? Network delivery segment size se chunked hoti hai; receiver jo hai woh drain karta hai. Ek plausible sequence hai
1024, 1024, 952— teen calls jo 3000 pe sum karte hain. Exact split guaranteed nahi hai; sirf total aur order hain. - Loop tab tak jab tak 3000 bytes collect na ho jaayein (ya
b''na mile). Yeh step kyun? Tumhe padhte rehna hoga — bade data ke liye ekrecvalmost kabhi bhi poora message nahi hota.
Example 4 — Cell D: the degenerate input, recv returns b'' (TCP)
- Ek clean close peer ko ek FIN bhejta hai.
Yeh step kyun?
close()OS ko kehta hai "mere se aur bytes nahi". Receiver ka stream apne end pe pahunch jaata hai. - Ek closed stream pe
recvempty bytes objectb''return karta hai. Yeh step kyun?b''socket ka tarika hai EOF kehne ka — end of file, matlab peer ne hang up kar liya. Yeh "client ne kuch nahi bheja" nahi hai. - Server ko loop break karna chahiye.
Yeh step kyun? Agar tum
b''ke liye test nahi karte, to tumb''lete hue forever loop karte ho aur CPU spin karte ho.
while True:
data = conn.recv(1024)
if data == b'': # ya: if not data
break # peer closed — EOF
conn.sendall(data)Example 5 — Cell E: UDP preserves boundaries
- Har
sendtoek self-contained datagram hai. Yeh step kyun? UDP messages carry karta hai, stream nahi."AA"aur"BB"ke beech ki boundary packet structure mein baked in hai. - Har
recvfromexactly ek datagram return karta hai. Yeh step kyun? Tum do UDP packets ko ek read mein merge nahi kar sakte, aur ek ko do reads mein split nahi kar sakte. Ek packet ↔ ekrecvfrom. - Result (no loss): teen calls
b"AA",b"BB",b"CC"return karte hain — kabhib"AABBCC"nahi.

Example 6 — Cell F: the ugly case, loss aur reorder (UDP)
- UDP koi delivery guarantee nahi deta.
Yeh step kyun? Koi handshake nahi, koi ack nahi, koi retransmit nahi. Load ke neeche ek router simply packet
3discard kar deta hai. - UDP koi ordering guarantee nahi deta.
Yeh step kyun? Packets alag paths le sakte hain;
42se pehle aa sakta hai. Boundaries abhi bhi preserved hain (har read ek poora packet hai), lekin sequence nahi. - Possible received sequence:
1, 4, 2, 5— chaar datagrams, ek lost, do swapped.
Example 7 — Cell G: real-world fix, length-prefix framing (TCP)
- Payload ko uski length ke 4-byte big-endian integer se prefix karo.
Yeh step kyun? Kyunki TCP mein koi boundaries nahi hain (Ex 2 & 3), receiver ko ek explicit "N bytes aa rahe hain" chahiye.
11big-endian packed hai\x00\x00\x00\x0b. - Wire bytes = 4 (header) + 11 (payload) = 15 bytes.
Yeh step kyun? Receiver pehle exactly 4 bytes padhta hai,
N = 11decode karta hai, phirrecvloop karta hai jab tak usne 11 aur collect nahi kar liye. - Receiver algorithm: 4 padho →
Nlo →Npadho. Ab boundaries recover ho jaati hain chahe TCP ne kuch bhi chunk kiya ho.
import struct
def send_msg(sock, payload):
header = struct.pack('>I', len(payload)) # 4-byte big-endian length
sock.sendall(header + payload)
def recv_exact(sock, n):
buf = b''
while len(buf) < n:
chunk = sock.recv(n - len(buf))
if chunk == b'': # EOF (Ex 4!)
raise ConnectionError("peer closed mid-message")
buf += chunk
return buf
def recv_msg(sock):
n = struct.unpack('>I', recv_exact(sock, 4))[0]
return recv_exact(sock, n)Example 8 — Cell H: exam twists aur wrong-protocol traps
(a) UDP with listen/accept:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.listen(5) # ???SOCK_DGRAMUDP hai; UDP connectionless hai. Yeh step kyun?listen/acceptconnections set up karte hain, jo UDP ke paas nahi hote. YehOSErrorraise karta hai. UDP sirfbindkarta hai phirrecvfrom/sendto.
(b) Ek str bhejna:
c.send("hi") # ???- Sockets bytes carry karte hain,
strnahi. Yeh step kyun?sendko bytes-like object chahiye → yehTypeErrorraise karta hai. Fix:c.send(b"hi")ya"hi".encode().
(c) Client jo bind karta hai vs jo nahi karta:
c.connect(('127.0.0.1', 9000)) # iske pehle koi bind nahi- Client ko
bindki zaroorat nahi hoti. Yeh step kyun?connectpe OS automatically ek ephemeral port assign kar deta hai (dekho Ports and IP addressing). Sirf server ko, jishe doosre find karte hain, ek fixedbindchahiye.
(d) Fast restart, no SO_REUSEADDR:
s.bind(('127.0.0.1', 9000)) # pichla server close hone ke baadOSError: Address already in useraise ho sakta hai. Yeh step kyun? Purana socketTIME_WAITmein linga rehta hai (dekho TIME_WAIT and SO_REUSEADDR).bindse pehleSO_REUSEADDRset karne se tum port immediately reclaim kar sakte ho.
Flashcards
TCP mein, teen sendall calls kitne recv calls ke roop mein aa sakti hain?
recv bhi ho sakta hai (stream coalescing).TCP mein recv() ka b'' return karna kya matlab hai?
Kya UDP datagrams merge ya split karta hai?
sendto exactly ek recvfrom ke barabar hota hai.