Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Python

Lập trình Socket đa luồng (Multi-threading) trong Python

Khái niệm đa luồng

Thread là luồng con trong tiến trình, thực thi độc lập nhưng chia sẻ bộ nhớ. Multithreading chạy nhiều thread đồng thời trong một tiến trình. Python triển khai đơn giản nhờ threading module.

Module threading vs _thread

  • _thread (Python 3) / thread (Python 2): Tạo thread như function
  • threading: Đối tượng hóa thread (OOP), khuyến nghị dùng

Cú pháp _thread

_thread.start_new_thread(func, args[, kwargs])

Ví dụ Client-Server đa luồng

Client (client_thread1.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("Nhập 'quit' để thoát")
    message = input(" -> ")
    
    while message != 'quit':
        soc.sendall(message.encode("utf8"))
        if soc.recv(5120).decode("utf8") == "-":
            pass
        message = input(" -> ")
    
    soc.send(b'--quit--')

if __name__ == "__main__":
    main()

Server (server_thread1.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:", sys.exc_info())
        sys.exit()
    
    soc.listen(6)
    print("Socket now listening")
    
    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:
            print("Client 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 exceeds limit: {}".format(client_input_size))
    decoded_input = client_input.decode("utf8").rstrip()
    return process_input(decoded_input)

def process_input(input_str):
    print("Processing input from client")
    return "Hello " + str(input_str).upper()

if __name__ == "__main__":
    main()

Chạy và kiểm tra

# Terminal 1: Chạy server
python server_thread1.py
# Socket created
# Socket now listening

# Terminal 2, 3, 4...: Chạy client
python client_thread1.py
# Nhập tin nhắn, gõ 'quit' để thoát

Kết quả server

Socket created
Socket now listening
Connected with 127.0.0.1:50275
Processing the input received from client
Processed result: Hello ZACK
Connected with 127.0.0.1:50282
Processing the input received from client
Processed result: Hello PYTHON
Processing the input received from client
Client is requesting to quit
Connection 127.0.0.1:50282 closed
...

Mỗi client được xử lý bởi một thread riêng biệt, cho phép server phục vụ nhiều client đồng thời.