使用Python Requests指定出站端口问题再探讨
解决连续发送HTTP请求时端口占用问题
问题原因
快速连续发送请求时,首次使用的本地端口会进入TIME_WAIT状态(TCP协议为确保数据完整传输的正常机制),系统默认不会立刻复用该端口,若第二次请求仍尝试使用同一个端口,就会触发Address already in use错误。
解决方案
1. 使用Session复用连接
利用requests.Session管理连接池,复用已有TCP连接,避免每次请求新建端口:
import requests # 创建会话对象 session = requests.Session() # 连续发送请求,复用同一连接 resp1 = session.get("http://192.168.1.140:8082/dev2/presence/notpresent") resp2 = session.get("http://192.168.1.140:8082/dev2/presence/notpresent") # 结束后关闭会话(可选,程序退出时会自动释放) session.close()
Session会自动维护连接状态,无需手动处理端口复用,是最简便的解决方案。
2. 自定义适配器允许端口复用
若必须指定固定本地端口,通过修改Socket选项强制允许复用处于TIME_WAIT状态的端口:
import requests from requests.adapters import HTTPAdapter from urllib3.poolmanager import PoolManager import socket class ReusablePortAdapter(HTTPAdapter): def init_poolmanager(self, *args, **kwargs): # 开启端口复用选项 kwargs["socket_options"] = [ (socket.SOL_SOCKET, socket.SO_REUSEADDR, 1), (socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) ] super().init_poolmanager(*args, **kwargs) # 配置会话并挂载适配器 session = requests.Session() session.mount("http://", ReusablePortAdapter()) # 指定固定本地端口发送请求 resp1 = session.get( "http://192.168.1.140:8082/dev2/presence/notpresent", source_address=("0.0.0.0", 你的本地端口号) # 替换为实际要使用的本地端口 ) resp2 = session.get( "http://192.168.1.140:8082/dev2/presence/notpresent", source_address=("0.0.0.0", 你的本地端口号) )
SO_REUSEADDR允许复用TIME_WAIT状态的端口,SO_REUSEPORT支持多进程/线程共享同一端口,两者结合可彻底解决固定端口的占用问题。
3. 放弃固定本地端口(推荐)
若业务无需指定固定本地端口,删除请求中的source_address参数,让系统自动分配可用端口,从根源避免端口冲突:
import requests # 无需指定本地端口,系统自动分配 resp1 = requests.get("http://192.168.1.140:8082/dev2/presence/notpresent") resp2 = requests.get("http://192.168.1.140:8082/dev2/presence/notpresent")
内容的提问来源于stack exchange,提问作者Prometheus
相关产品推荐
相关产品推荐

