Loading Page Content...
Preparing courses, live labs, and learning resources.सामग्री लोड हो रही है, कृपया प्रतीक्षा करें...
Preparing courses, live labs, and learning resources.सामग्री लोड हो रही है, कृपया प्रतीक्षा करें...
Building a real-time, multi-client chat server requires managing multiple persistent TCP socket connections simultaneously. While a multithreaded architecture (one thread per client) quickly runs into thread memory limits and lock contention, an Asynchronous Event-Driven Architecture powered by asyncio scales effortlessly to thousands of concurrent users on a single operating system thread.
The server maintains a registry of connected client stream writers. When any client sends a message, the server broadcasts it to all other connected peers:
StreamReader & StreamWriterInstead of handling raw low-level socket buffers and manual byte framing, asyncio provides high-level stream abstractions:
asyncio.start_server(client_connected_cb, host, port): Creates a non-blocking TCP socket server.StreamReader.readline(): Reads bytes until a newline delimiter \n, cleanly solving the TCP framing problem.StreamWriter.write() and await StreamWriter.drain(): Buffers outgoing bytes and flushes the socket's write buffer.How data and code flow step-by-step
The client connects to the server and runs two concurrent coroutines: one for reading incoming server broadcasts and another for writing user messages:
How data and code flow step-by-step
await writer.drain(): Ensures that outgoing byte buffers are emptied into the OS network stack without memory bloating if a slow client lags behind.finally blocks, preventing memory and descriptor leaks.When a client disconnects unexpectedly, broadcasting to its socket raises ConnectionResetError or BrokenPipeError. Always wrap socket sends in try...except and remove stale client handles.
In multi-threaded chat servers, iterate over a copy of the active clients list (list(clients)) to prevent RuntimeError: dictionary changed size during iteration.
Build a thread-safe message broadcast function that relays an incoming chat message to all connected client sockets.
Which high-level asyncio function creates and starts a non-blocking TCP socket server? A. asyncio.create_tcp_listener() B. asyncio.start_server() C. socket.socket() D. asyncio.run_server()
asyncio.start_server(callback, host, port) initializes an asynchronous TCP socket server, invoking the callback with a (StreamReader, StreamWriter) pair whenever a client connects.Why is calling await writer.drain() essential after executing writer.write(data)? A. It compiles the data to JSON. B. It flushes the internal write buffer to the network socket, pausing execution cooperatively if the operating system socket buffer is full (backpressure management). C. It disconnects the client. D. It resets the client's IP address.
writer.write() simply queues bytes into an in-memory buffer. await writer.drain() flushes the buffer to the OS and yields control to avoid memory ballooning if the socket buffer is full.How does the chat server distinguish between distinct message boundaries sent by clients over a continuous TCP stream? A. By relying on reader.readline(), which reads until a newline character (\n) is encountered. B. TCP automatically splits messages into separate packets. C. By pausing for 1 second between every sentence. D. By inspecting HTTP headers.
\n), which reader.readline() evaluates cleanly.What happens if a connected client suddenly terminates its application or unplugs its network connection? A. The server halts immediately with an unhandled exception. B. reader.readline() returns an empty byte string (b""), allowing the server to cleanly remove the client in its finally block. C. The server reboots. D. The event loop crashes.
b""), signaling the end of input so cleanup logic can execute.Why is an asyncio-based chat server significantly more scalable than a traditional one-thread-per-client threaded server? A. Coroutines use zero CPU. B. Coroutines require only a few kilobytes of RAM each and run on a single event-loop thread without kernel context-switching overhead, whereas threads consume megabytes of stack RAM each. C. Threads cannot communicate with each other. D. Sockets only work in asynchronous mode.
In the next lesson, we will continue your advanced Python journey with Project: Simple Client-Server Application (10: Networking with Python).
👉 Continue to Next Lesson: Project: Simple Client-Server Application →
Continue learning with hands-on practice, examples, and exercises in the upcoming topic.
| Previous Lesson | Next Lesson |
|---|---|
| TCP vs UDP | Project: Simple Client-Server Application |
Test your understanding of this lesson with 5 questions. Each question has one correct answer.