P2P网络中Socket监听的while循环结束后代码无法执行问题
问题分析与修复方案
你的代码里socket.recvfrom(1024)是阻塞式调用——只要没有客户端发送数据返回,程序就会一直卡在这个调用上等待,哪怕time.time() < end的条件已经不满足。这就是循环无法自动退出、最后一行打印代码永远执行不到的核心原因。
另外注意:原代码缺少import time语句,运行时会直接报错,必须补上。
修复方案一:给Socket设置超时时间
通过给UDP Socket设置超时时间,让recvfrom在指定时间内没收到数据就抛出异常,我们可以捕获异常后继续检查循环是否到期:
from socket import * import time # 必须导入time模块 server_socket = socket(AF_INET, SOCK_DGRAM) server_socket.bind(('', line)) # line为服务器端口号(需是整数) server_socket.settimeout(1) # 设置每次recv最多等待1秒 online = [] for p in clients: # clients为所有客户端地址列表 server_socket.sendto('ping'.encode(), p) end = time.time() + 10 while time.time() < end: try: message, peer = server_socket.recvfrom(1024) print('pong ', peer) online.append(peer) except timeout: # 超时后继续判断是否还在10秒窗口内 continue # 可选:去重,避免同一客户端多次返回导致重复记录 online = list(set(online)) print('online: ', online)
修复方案二:用select精确控制等待时间
使用select模块监听Socket的可读事件,同时传入剩余的等待时间,这样可以更精准地控制整个循环的10秒时限:
from socket import * import time import select server_socket = socket(AF_INET, SOCK_DGRAM) server_socket.bind(('', line)) online = [] for p in clients: server_socket.sendto('ping'.encode(), p) end = time.time() + 10 while time.time() < end: remaining_time = end - time.time() if remaining_time <= 0: break # 监听Socket是否有数据可读,超时时间为剩余的10秒窗口时间 ready_sockets, _, _ = select.select([server_socket], [], [], remaining_time) if ready_sockets: message, peer = server_socket.recvfrom(1024) print('pong ', peer) online.append(peer) online = list(set(online)) print('online: ', online)
额外注意事项
- 如果客户端可能重复发送pong响应,建议用集合存储在线客户端地址,避免重复记录;
- 确保
line是整数类型的端口号,clients是合法的客户端地址元组列表(格式如('192.168.1.100', 8080))。
内容的提问来源于stack exchange,提问作者Mahdi
相关产品推荐
相关产品推荐

