Python TCP Socket超时后连接对象状态及关闭方式咨询
关于TCP连接超时后连接对象的状态与关闭问题
超时触发后的默认行为
当你在conn上设置settimeout(5)后,conn.recv()如果5秒内未收到数据,会直接抛出socket.timeout异常。你的当前服务器代码没有捕获这个异常,程序会立刻终止运行。此时虽然with conn上下文管理器理论上会在退出时自动调用conn.close(),但由于程序是异常崩溃退出,这个自动关闭的过程可能不完整,连接资源无法保证被正确释放。
是否需要手动调用conn.close()
- 正常场景下:如果用
with语句管理conn对象,无论正常退出代码块还是捕获异常后退出,with都会自动调用conn.close(),不需要手动调用。你代码中收到"shutdown"时手动执行conn.close()属于多余操作,with块结束后会自动完成关闭。 - 超时异常场景下:由于当前代码未捕获超时异常,程序直接崩溃,
with的自动关闭逻辑可能无法执行。因此必须捕获socket.timeout异常,在异常处理中根据业务需求选择:- 继续等待:重置超时后回到循环,保持连接
- 关闭连接:手动调用
conn.close()或退出with块,让管理器自动关闭
优化后的服务器代码示例
import socket, os if __name__ == "__main__": host = '0.0.0.0' port = 50053 with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.bind((host, port)) print(f"Server (host : {host}) (port : {port}) (pid : {os.getpid()}) listening....") s.listen() conn, addr = s.accept() with conn: print('\tConnected by address :', addr) while True: try: conn.settimeout(5) data = conn.recv(1024).decode() conn.settimeout(None) if not data: # 客户端主动关闭连接,recv返回空值 break if data == "shutdown": break print(f"\t\tReceived {data}") except socket.timeout: print("\tTimeout: No data received in 5 seconds") # 可选操作:关闭连接并退出循环 # conn.close() # break # 或继续等待,回到循环重新设置超时 continue
关键修改说明
- 新增
try-except块捕获socket.timeout异常,避免程序崩溃 - 处理
recv()返回空的情况(客户端主动断开连接的场景) - 移除多余的手动
conn.close()调用,依赖with管理器自动释放资源
内容的提问来源于stack exchange,提问作者GaetanG
相关产品推荐
相关产品推荐

