Python Socket报OSError: [Errno 98] Address already in use
报错根因
这个报错不是代码逻辑错误,是TCP协议的TIME_WAIT机制导致的:当TCP连接主动关闭后,对应的端口会进入一段时长为2倍最大报文生存时间(MSL,通常1~4分钟)的TIME_WAIT状态,这段时间内内核不会把该端口的绑定权限交出来,重启服务端再去bind同一个地址和端口,就会触发OSError: [Errno 98] Address already in use。
解决方法
方法1:服务端开启端口地址复用(调试/生产环境都推荐)
在socket创建完成、执行bind操作之前,给socket加上SO_REUSEADDR配置,允许进程直接绑定处于TIME_WAIT状态的端口,不用干等端口自然释放。
修改后的服务端核心代码:
import socket serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 新增:允许复用处于TIME_WAIT状态的端口 serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) host = socket.gethostname() port = 9876 serversocket.bind((host, port)) serversocket.listen(5) while True: clientsocket, addr = serversocket.accept() print("Got a connection from %s" % str(addr)) msg = 'Thank you for connecting' + "\r\n" clientsocket.send(msg.encode('ascii')) clientsocket.close()
方法2:临时手动释放占用端口
如果临时不想改代码,找到当前占用9876端口的进程直接终止就行:
- Linux/macOS 终端执行
lsof -i :9876,拿到结果里对应进程的PID,再执行kill -9 <拿到的PID>就可以释放端口 - Windows 命令行执行
netstat -ano | findstr :9876,拿到结果里对应进程的PID,去任务管理器的详细信息页结束对应PID的进程即可
补充说明
- 开发调试阶段频繁重启服务时,每次手动杀进程效率极低,优先用
SO_REUSEADDR配置,一劳永逸 - 这个配置只需要在服务端创建socket后、bind之前设置就行,客户端socket不需要加这个配置
内容的提问来源于stack exchange,提问作者Melany
相关产品推荐
相关产品推荐

