Computer >> Máy Tính >  >> Lập trình >> Python

Lập trình socket với đa luồng trong Python?

Khái niệm đa luồng

Đa luồng là khái niệm cốt lõi của gần như tất cả các ngôn ngữ lập trình hiện đại, đặc biệt là python vì cách triển khai các luồng đơn giản của nó.

Một luồng là một chương trình con trong một chương trình có thể được thực thi độc lập với phần khác của mã. Một chuỗi thực thi trong cùng các tài nguyên có thể chạy được của chương trình chia sẻ ngữ cảnh như bộ nhớ.

Khi trong một quá trình duy nhất, chúng ta đang thực hiện đồng thời nhiều luồng, nó được gọi là đa luồng.

Mô-đun đa luồng Python để triển khai luồng

Để triển khai các luồng trong chương trình, python cung cấp hai mô-đun -

  • luồng (đối với python 2.x) hoặc mô-đun _thread (đối với python 3.x)
  • mô-đun phân luồng

Trong đó mô-đun luồng tạo một luồng dưới dạng một chức năng trong khi mô-đun luồng cung cấp cách tiếp cận hướng đối tượng để tạo một luồng.

Cú pháp

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

Ở trên bắt đầu một chuỗi mới và trả về định danh của nó. Đối số đầu tiên là một hàm func mà luồng thực thi với đối số thứ hai chứa một bộ dữ liệu với danh sách vị trí các đối số. Đối số kwargs tùy chọn chỉ định một từ điển các đối số từ khóa. Khi hàm trả về, chuỗi sẽ âm thầm tồn tại.

Trong phần này, chúng ta thấy một ví dụ cơ bản về ứng dụng máy khách-máy chủ. Nơi mà các máy khách về cơ bản mở một kết nối socket và gửi các truy vấn đến máy chủ. Máy chủ phản hồi lại.

Khi chạy mà không có đối số, chương trình này bắt đầu với máy chủ ổ cắm TCP lắng nghe các kết nối tới 127.0.0.1 trên cổng 8000.

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("Please enter 'quit' to exit")
   message = input(" -> ")
   while message != 'quit':
      soc.sendall(message.encode("utf8"))
      if soc.recv(5120).decode("utf8") == "-":
         pass # null operation
      message = input(" -> ")
   soc.send(b'--quit--')
if __name__ == "__main__":
   main()

Trong khi chương trình máy chủ là,

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 # arbitrary non-privileged port
   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- do not reset for every requests
   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 clientThread(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 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("The input size is 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 the input received from client")
   return "Hello " + str(input_str).upper()
if __name__ == "__main__":
   main()

Khi chạy tập lệnh trên, hãy chạy server_thread1.py trong thiết bị đầu cuối dưới dạng,

python server_thread1.py
Socket created
Socket now listening

Chúng tôi sẽ xem cửa sổ máy chủ và hiểu quy trình. Bây giờ, hãy mở nhiều thiết bị đầu cuối ứng dụng khách, chạy chuỗi ứng dụng khách

python client_thread1.py
Enter 'quit' to exit
-> Zack
->

Trong một thiết bị đầu cuối khác, hãy chạy một chương trình khách khác và đồng thời xem cửa sổ đầu cuối của máy chủ,

python client_thread1.py
Enter 'quit' to exit
-> Python
-> quit

Một thiết bị đầu cuối khác, chạy chuỗi ứng dụng,

python client_thread1.py
Enter 'quit' to exit
-> world!
-> Anothny
->

Và chúng tôi có thể thấy cửa sổ máy chủ của chúng tôi sẽ hiển thị đầu ra giống như,

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
Connected with 127.0.0.1:50285
Processing the input received from client
Processed result: Hello WORLD!
Processing the input received from client
Processed result: Hello ANOTHNY

Vì vậy, các luồng cung cấp một trong những kỹ thuật phổ biến nhất để xử lý nhiều kết nối ổ cắm và máy khách.