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 ?

  • _thread module ? Creates threads as functions (low-level)
  • threading module ? 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.

Updated on: 2026-03-25T05:25:22+05:30

5K+ Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements