📧 Interprocess Communication: Client and Server
🎯 Learning Objective
- Understand interprocess communication (IPC) mechanisms using sockets.
- Create a server and a client in Python.
- Identify the role of the operating system in managing network connections.
📜 Statement
In this exercise, you will create a simple communication application between a client and a server using sockets in Python.
🔧 Step 1 – Create a Simple Server
A server:
- Opens a "door" (called a port) on your computer.
- Waits for a client to connect.
- Receives messages from the client.
Server Code
Create a file called server.py and copy the following code:
import socket
# Create a TCP socket
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# The IP address and port to use
host = 'localhost'
port = 12345
# Bind the socket to the address
server.bind((host, port))
# Listen for up to 1 connection
server.listen(1)
print("[Server] Waiting for connection...")
# Accept the connection
connection, address = server.accept()
print(f"[Server] Connection from {address}")
# Receive messages
while True:
message = connection.recv(1024).decode()
if message.lower() == "exit":
print("[Server] End of communication.")
break
print(f"[Client] {message}")
# Close the connections
connection.close()
server.close()
Test
This program does nothing until a client connects. Start the server with the command:
python server.py
and connect with your web browser by going to http://localhost:12345.
You can stop the server by pressing Ctrl+C in the terminal.
💬 Step 2 – Create a Client
A client:
- Connects to a server (here via
localhostand the port). - Sends messages that you type in the console.
2.1 Client Code
Create a file client.py:
import socket
# Create a TCP socket
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Connect to the server
client.connect(('localhost', 12345))
print("[Client] Connected to the server. Type your messages:")
# Read and send messages
while True:
message = input(">>> ")
client.sendall(message.encode())
if message.lower() == "exit":
break
# Close the connection
client.close()
2.2 Test
- In one terminal: run
python server.py - In another terminal: run
python client.py - Exchange a few messages.
- Type
exitto stop.
🔁 Step 3 – Two-Way Communication
Currently, only the client talks and the server listens. We will now allow the server to respond.
3.1 Use threading to Listen and Write Simultaneously
Create a file called server2.py and copy the following code:
import socket
import threading
def receive(connection):
while True:
try:
message = connection.recv(1024).decode()
if not message or message.lower() == "exit":
print("[Client] has left the conversation.")
print("[Server >>>] ", end="", flush=True)
break
print(f"[Client] {message}")
print("[Server >>>] ", end="", flush=True)
except: # noqa: E722
break
def send(connection):
while True:
try:
message = input("[Server >>>] ")
connection.sendall(message.encode())
if message.lower() == "exit":
break
except: # noqa: E722
break
# Create the server
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('localhost', 12345))
server.listen(1)
print("[Server] Waiting for connection...")
connection, address = server.accept()
print(f"[Server] Connected to {address}")
# Start the threads
thread1 = threading.Thread(target=receive, args=(connection,))
thread2 = threading.Thread(target=send, args=(connection,))
thread1.start()
thread2.start()
thread1.join()
thread2.join()
connection.close()
server.close()
Create a file called client2.py and copy the following code:
import socket
import threading
def receive(sock):
while True:
message = sock.recv(1024).decode()
if message.lower() == "exit":
print("[Server] has left the conversation.")
print("[Client >>>] ", end="", flush=True)
break
print(f"[Server] {message}")
print("[Client >>>] ", end="", flush=True)
def send(sock):
while True:
message = input("[Client >>>] ")
sock.sendall(message.encode())
if message.lower() == "exit":
break
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(('localhost', 12345))
print("[Client] Connected to the server.")
# Start the threads
thread1 = threading.Thread(target=receive, args=(client,))
thread2 = threading.Thread(target=send, args=(client,))
thread1.start()
thread2.start()
thread1.join()
thread2.join()
client.close()
✅ Expected Result
- Run
server2.pyin one terminal. - Run
client2.pyin another. - Try exchanging messages in both directions.
- Cleanly close with
exit.

📝 Step 4 – The Operating System
The operating system plays a crucial role in managing network connections. It manages resources, ports, and ensures that data is sent and received correctly. The same goes for threads, which allow multiple tasks to be executed in parallel, like listening and sending messages at the same time.
Answer the following questions:
- In the server and client code, when is the operating system involved?
- Are the threads managed by the operating system (OS thread) or by Python (application thread)?
- Why is it important to close connections properly?
- What happens if you try to run the server multiple times on the same port without closing it?
- What happens if you try to run the client before the server?