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ư functionthreading: Đố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.