如何暂停与恢复Python socketserver?官方文档未找到相关方法
实现socketserver的暂停与恢复功能
我刚查过Python 3.4的socketserver文档,确实没有内置的暂停/恢复机制,不过我们可以通过线程安全的控制标志来实现这个需求。下面是具体的实现思路和代码示例:
核心思路
socketserver的serve_forever()会持续处理请求,我们可以用threading.Event这个线程安全的事件对象,来控制请求处理的流程:
- 初始时设置事件为"允许处理"状态
- 收到
offline 5指令时,将事件切换为"暂停"状态,睡眠指定时间后再切回"允许处理"状态 - 在请求处理方法中,先检查事件状态,只有允许时才处理请求
完整代码示例
import socketserver import threading import time HOST = "localhost" PORT = 9999 class MyUDPHandler(socketserver.BaseRequestHandler): def handle(self): # 循环等待服务恢复运行状态,避免空转占用过多CPU while not self.server.running_event.is_set(): time.sleep(0.1) data = self.request[0].strip() socket = self.request[1] client_msg = data.decode('utf-8') print(f"Received from {self.client_address}: {client_msg}") # 解析offline指令 msg_parts = client_msg.split() if len(msg_parts) == 2 and msg_parts[0] == "offline": try: delay = int(msg_parts[1]) print(f"Pausing server for {delay} seconds...") # 切换为暂停状态 self.server.running_event.clear() time.sleep(delay) # 恢复运行状态 self.server.running_event.set() print("Server resumed.") socket.sendto(b"Server paused and resumed successfully", self.client_address) except ValueError: socket.sendto(b"Error: Invalid delay value", self.client_address) else: # 正常处理其他请求(这里示例是回声) socket.sendto(b"Echo: " + data, self.client_address) if __name__ == "__main__": # 初始化UDP服务 server = socketserver.UDPServer((HOST, PORT), MyUDPHandler) # 添加线程安全的事件控制对象,初始为允许运行状态 server.running_event = threading.Event() server.running_event.set() # 启动服务线程 server_thread = threading.Thread(target=server.serve_forever, args=()) server_thread.daemon = False server_thread.start() print(f"UDP server running on {HOST}:{PORT}") print("Press Ctrl+C to shut down the server") # 主线程保持运行,等待中断信号 try: while True: time.sleep(1) except KeyboardInterrupt: print("\nShutting down server...") server.shutdown() server.server_close()
关键细节说明
- 线程安全控制:
threading.Event是专门用于线程间同步的对象,is_set()、clear()、set()方法都是线程安全的,不会出现竞态问题。 - 单线程服务适配:默认的
UDPServer是单线程的,所以在handle()方法中睡眠时,服务会完全暂停处理新请求,符合需求。如果使用ThreadingUDPServer(多线程版本),需要调整逻辑(比如用全局标志+锁)来确保所有线程都暂停。 - 控制台触发可选:如果需要从控制台输入
offline 5而不是客户端发送指令,可以把指令解析逻辑移到主线程的输入监听中,替换上面的while True: time.sleep(1)部分:try: while True: cmd = input("Enter command (offline <seconds>): ").strip() if cmd.startswith("offline"): parts = cmd.split() if len(parts) == 2: try: delay = int(parts[1]) print(f"Pausing server for {delay} seconds...") server.running_event.clear() time.sleep(delay) server.running_event.set() print("Server resumed.") except ValueError: print("Invalid delay value, must be an integer.") else: print("Usage: offline <seconds>") except KeyboardInterrupt: # 关闭服务逻辑...
内容的提问来源于stack exchange,提问作者merry-go-round
相关产品推荐
相关产品推荐

