在Python中使用多线程进行套接字编程?
多线程概念
多线程是几乎所有现代编程语言(尤其是python)的核心概念,因为它的线程实现简单。
线程是程序内的子程序,可以独立于代码的其他部分执行。线程在同一上下文中执行,以共享程序的可运行资源(如内存)。
当在一个进程中,我们同时执行多个线程时,称为多线程。
用于线程实现的Python多线程模块
为了在程序中实现线程,python提供了两个模块-
线程(对于python2.x)或_thread(对于python3.x)模块
穿线模块
线程模块将线程创建为函数,而线程模块提供面向对象的方法来创建线程。
语法
_thread.start_new_thread(func, args[, kwargs])
上面启动了一个新线程并返回其标识符。第一个参数是函数func,线程将使用第二个参数执行该函数,该第二个参数包含具有参数位置列表的元组。可选的kwargs参数指定关键字参数的字典。当函数返回时,线程静默地存在。
在此,我们看到了客户端-服务器应用程序的基本示例。客户端从根本上打开套接字连接并将查询发送到服务器。服务器响应。
在不带任何参数的情况下运行,该程序从一个TCP套接字服务器启动,该服务器侦听端口8000上与127.0.0.1的连接。
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()
服务器程序是
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("线程未启动。") 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()
在运行上述脚本时,请在终端中以以下方式运行server_thread1.py,
python server_thread1.py Socket created Socket now listening
我们将观看服务器窗口并了解流程。现在打开多个客户端终端,运行客户端线程
python client_thread1.py Enter 'quit' to exit -> Zack ->
在另一个终端中,也运行另一个客户端程序并监视服务器终端窗口,
python client_thread1.py Enter 'quit' to exit -> Python -> quit
另一个终端,运行客户端线程,
python client_thread1.py Enter 'quit' to exit -> world! -> Anothny ->
我们可以看到我们的服务器窗口将显示类似以下的输出,
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
因此,线程提供了一种最常见的技术来处理多个套接字连接和客户端。