Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
Socket Programming with Multi-threading in Python?
Socket programming with multi-threading allows a server to handle multiple clients simultaneously. While a basic socket server can only serve one client at a time, multi-threading creates separate threads for each client connection, enabling concurrent communication.
Multithreading Concepts
Multithreading is a core concept in modern programming languages, especially Python, due to its simple thread implementation. A thread is a sub-program within a program that executes independently while sharing the program's resources like memory. When multiple threads execute simultaneously within a single process, it's called multithreading.
Python Threading Modules
Python provides two modules for thread implementation ?
-
_threadmodule ? Creates threads as functions (low-level) -
threadingmodule ? Provides object-oriented approach (recommended)
The threading module is preferred as it offers better control and easier thread management.
Thread Creation Syntax
_thread.start_new_thread(func, args[, kwargs])
This starts a new thread with the specified function func, arguments args, and optional keyword arguments kwargs. However, we'll use the threading module for better control.
Multi-threaded Server Example
Here's a complete client-server application where the server handles multiple clients using threads ?
Client Code (client_thread.py)
import socket
import sys
def main():
soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = "127.0.0.1"
port = 8000
try:
soc.connect((host, port))
except:
print("Connection Error")
sys.exit()
print("Please enter 'quit' to exit")
message = input(" -> ")
while message != 'quit':
soc.sendall(message.encode("utf8"))
response = soc.recv(5120).decode("utf8")
if response == "-":
pass # Server acknowledgment
message = input(" -> ")
soc.send(b'--quit--')
soc.close()
if __name__ == "__main__":
main()
Server Code (server_thread.py)
import socket
import sys
import traceback
from threading import Thread
def main():
start_server()
def start_server():
host = "127.0.0.1"
port = 8000
soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
soc.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
print("Socket created")
try:
soc.bind((host, port))
except:
print("Bind failed. Error : " + str(sys.exc_info()))
sys.exit()
soc.listen(6) # Queue up to 6 requests
print("Socket now listening")
# Infinite loop for accepting connections
while True:
connection, address = soc.accept()
ip, port = str(address[0]), str(address[1])
print("Connected with " + ip + ":" + port)
try:
Thread(target=client_thread, args=(connection, ip, port)).start()
except:
print("Thread did not start.")
traceback.print_exc()
soc.close()
def client_thread(connection, ip, port, max_buffer_size=5120):
is_active = True
while is_active:
client_input = receive_input(connection, max_buffer_size)
if "--quit--" in client_input.lower():
print("Client is requesting to quit")
connection.close()
print("Connection " + ip + ":" + port + " closed")
is_active = False
else:
print("Processed result: {}".format(client_input))
connection.sendall("-".encode("utf8"))
def receive_input(connection, max_buffer_size):
client_input = connection.recv(max_buffer_size)
client_input_size = sys.getsizeof(client_input)
if client_input_size > max_buffer_size:
print("Input size greater than expected: {}".format(client_input_size))
decoded_input = client_input.decode("utf8").rstrip()
result = process_input(decoded_input)
return result
def process_input(input_str):
print("Processing input from client")
return "Hello " + str(input_str).upper()
if __name__ == "__main__":
main()
Running the Example
First, start the server ?
python server_thread.py Socket created Socket now listening
Then run multiple clients in separate terminals ?
python client_thread.py Please enter 'quit' to exit -> Hello World -> quit
The server output shows multiple concurrent connections ?
Socket created Socket now listening Connected with 127.0.0.1:50275 Processing input from client Processed result: Hello HELLO WORLD Connected with 127.0.0.1:50282 Processing input from client Processed result: Hello PYTHON Client is requesting to quit Connection 127.0.0.1:50282 closed
How It Works
The server creates a new thread for each client connection using Thread(target=client_thread, args=(connection, ip, port)).start(). Each thread handles one client independently, allowing multiple clients to communicate with the server simultaneously without blocking each other.
Conclusion
Multi-threading in socket programming enables servers to handle multiple clients concurrently. Each client connection runs in its own thread, preventing blocking and allowing scalable client-server applications. The threading module provides an elegant way to implement this functionality in Python.
