Python socket settimeout()设置后recv()未生效问题咨询
Python socket settimeout 问题解答
核心认知纠正
你对settimeout()的理解存在两个关键偏差:
- 该方法设置的是阻塞操作的最长等待上限,不是固定等待时长。调用
recv()时如果socket接收缓冲区已经有数据,会立刻读取返回,不会等够设置的时间;只有缓冲区为空、需要等待对端发送新数据时,才会开始计时,等满设置的时长还没收到数据就抛出socket.timeout异常。 - 超时设置是持久生效的,不会只触发一次。只要你不重新调用
settimeout()修改参数,这个socket上所有后续阻塞操作(recv()/send()/accept()等)都会沿用这个超时阈值,且每次阻塞操作都会单独重新计时——也就是每次循环走到recv()需要等数据时,都会重新算3秒的等待窗口,不是设置完总共只等3秒。
你测试时recv未等待的原因
你的客户端在连接建立后立刻连续发送了3段数据,这些数据会被操作系统内核存在对应socket的接收缓冲区里。服务端调用recv()时缓冲区已经有数据,自然直接返回不会等待,看不到超时效果。
现有代码的问题
- 缩进完全错误:Python靠缩进区分代码块,你写的
if data:判断和最后一行print(sockets.recv())都在while True循环外,循环只会无限重复执行data = sockets.recv(30)这一行,逻辑不符合预期。 - 最后一行
recv()没有传入缓冲区大小参数,运行会直接抛出参数错误。 - 没有捕获
socket.timeout异常,真触发超时时代码会直接崩溃。
修正后的服务端参考代码:
import socket IP = "127.0.0.1" PORT = 8888 socketss = socket.socket(socket.AF_INET, socket.SOCK_STREAM) socketss.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) socketss.bind((IP, PORT)) socketss.listen() sockets, ip = socketss.accept() sockets.settimeout(3) while True: try: data = sockets.recv(30) if data: print(data) else: # recv返回空字节代表对端主动关闭了连接 print("连接已断开") break except socket.timeout: print("等待数据超时,可在这里编写超时后的处理逻辑") # 超时后可选择继续循环等待,或主动断开连接终止流程
如果要验证超时效果,修改客户端逻辑,建立连接发送一次数据后暂停超过3秒再发下一段,就能看到服务端正常触发超时逻辑。
内容的提问来源于stack exchange,提问作者Kenshie van Assche
相关产品推荐
相关产品推荐

