Python
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax and Data Types
-
Section 3: Collections
-
39: Set Operations: Union, Intersection, Difference
-
Section 4: Control Flow
-
Section 5: Functions
-
Section 6: Turtle Graphics and Early Practice Projects
-
Section 7: Working with Files and I/O
-
Section 8: Regular Expressions
-
Section 9: Object-Oriented Python
-
Section 10: Error Handling
-
Section 11: Modules and Packages
-
Section 12: Iterators, Generators, and Functional Tools
-
Section 13: Decorators and Metaprogramming
-
Section 14: Concurrency and Parallelism
-
Section 15: Working with Dates, Times, and Numbers
-
Section 16: Standard Library Deep Dive I: Data Structures
-
Section 17: Standard Library Deep Dive II: System and Introspection
-
Section 18: Standard Library Deep Dive III: Security and Encoding
-
Section 19: Standard Library Deep Dive IV: Text and Data Utilities
-
Section 20: Networking and Web Basics
-
Section 21: Working with Databases
-
Section 22: Testing and Quality
-
Section 23: Advanced Typing
-
Section 24: Context Managers and Resource Handling
-
Section 25: Text, Unicode, and Binary Data
-
Section 26: More Functional and Iteration Tools
-
Section 27: Data Validation and Configuration
-
Section 28: Working with Images and Media
-
Section 29: Property-Based and Documentation Testing
-
Section 30: Packaging and Deployment
-
Section 31: Performance and Internals
-
Section 32: Design Patterns in Python
-
Section 33: GUI Programming
-
Section 34: Security Basics
-
Section 35: Data Structures and Algorithms
-
Section 36: Practical Projects
-
Section 37: Capstone Projects
-
Section 38: Interview and Algorithm Practice
-
Section 39: Writing Idiomatic Python
272: Building a Simple TCP Client and Server
TCP (Transmission Control Protocol) is the reliable "handshake" of the internet. Unlike UDP, where you just throw packets at a destination and hope for the best, TCP ensures that every byte arrives in the correct order. Today, we're going to build a small "Server Health Probe." The idea is simple: a client will connect to a server, ask for its current status, and the server will respond with a health report.
Setting up the Listening Post
First, we need a server that sits and waits for a connection. In Python, the socket module is our primary tool here. I'm going to use AF_INET for IPv4 and SOCK_STREAM to tell Python we want a TCP connection.
import socket
# We'll use localhost and a non-privileged port
HOST = '127.0.0.1'
PORT = 65432
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind((HOST, PORT))
server_socket.listen()
print(f"Server is listening on {HOST}:{PORT}...")
while True:
# This blocks until a client connects
conn, addr = server_socket.accept()
print(f"Connected by {addr}")
data = conn.recv(1024)
if not data:
break
print(f"Received request: {data.decode()}")
# I'll send a simple status message back
conn.send("STATUS_OK: All systems nominal")
conn.close()
Wait, I just broke it
If you try to run that server code and connect to it, you'll hit a TypeError. I did this a dozen times when I first started with sockets. The error is: TypeError: a bytes-like object is required, not 'str'.
Here is the thing about sockets: they don't understand Python strings. They only understand bytes. When I called conn.send("STATUS_OK..."), I passed a string. I need to encode that string into bytes using UTF-8 before it hits the wire. I'll fix that line to: conn.send("STATUS_OK: All systems nominal".encode('utf-8')).
Connecting the Health Probe Client
Now that the server knows how to handle bytes, let's build the client. The client is much simpler; it doesn't need to bind or listen. It just needs to know where the server is and initiate the connection.
import socket
HOST = '127.0.0.1'
PORT = 65432
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as client_socket:
client_socket.connect((HOST, PORT))
# We have to encode the request string into bytes
request = "GET_HEALTH"
client_socket.sendall(request.encode('utf-8'))
# Now we wait for the response
response = client_socket.recv(1024)
print(f"Server responded: {response.decode('utf-8')}")
Refining the Communication Flow
You'll notice I used sendall() in the client instead of send(). This is a professional habit I highly recommend. send() doesn't guarantee that all the data was actually transmitted—it returns the number of bytes sent, and you're technically supposed to keep track of the offset and send the rest in a loop. sendall() handles that tedious loop for you under the hood, ensuring the entire message is pushed through the buffer.
When you run these two scripts—server first, then client—you'll see the server log the connection, and the client print the health status. We've just built a minimal version of how almost every web request starts.
📋 Practical Task
Build a Remote System Clock Synchronizer
Your task is to extend the client-server pattern we just learned to create a "Time Sync" service.
- The Server: Instead of returning a hardcoded "STATUS_OK" message, the server should import the
datetimemodule. When it receives a request, it should capture the current server time as a string and send that back to the client. - The Client: The client should send the request
"GET_TIME"and then print the received server time in a user-friendly format (e.g., "The server time is: 2023-10-27 14:30:05").
Ensure that both the client and server properly handle the encoding and decoding of bytes to avoid the TypeError we encountered in the lesson.
There are no comments for now.