You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Debian服务器上Python设置SO_REUSEADDR后仍出现“地址已被占用”错误求助

Debian服务器上Python设置SO_REUSEADDR后仍出现“地址已被占用”错误求助

我完全懂你这种困扰——脚本崩了之后端口就一直被占,明明加了SO_REUSEADDR还是没用,试了好几次都卡在这里,确实挺闹心的。咱们一步步来排查解决这个问题:

首先,确认端口是不是被残留进程占用了

很多时候出现这个错误,并不是SO_REUSEADDR没生效,而是之前崩溃的Python进程根本没完全退出,还攥着端口不放。你可以用这两个命令检查:

  • 用lsof查看端口关联的进程:
    lsof -i :1712
    
  • 或者用ss命令,输出更简洁:
    ss -tulpn | grep 1712
    

如果输出里能看到Python进程的PID,直接杀掉它就行:

kill -9 <进程PID>

杀掉之后再运行脚本,大概率就能正常绑定端口了。

然后,优化代码避免崩溃后残留socket连接

你的脚本目前没有任何异常处理逻辑,如果遇到Ctrl+C中断、意外崩溃的情况,socket可能不会被正常关闭,导致端口一直处于占用状态。咱们给代码加上安全退出的逻辑,确保不管怎么退出,socket都能被正确关闭:

import socket
import signal
import sys

# 处理Ctrl+C等中断信号,确保关闭socket后再退出
def signal_handler(sig, frame):
    print('正在关闭socket,准备退出...')
    s.close()
    sys.exit(0)

signal.signal(signal.SIGINT, signal_handler)

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 保留SO_REUSEADDR,再加上SO_REUSEPORT(部分系统需要这个参数才能彻底解决端口复用问题)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)

print("Socket successfully created")
port = 1712
s.bind(('', port))
print("socket binded to %s" %(port))
# put the socket into listening mode
s.listen(5)
print("socket is listening")

try:
    # a forever loop until we interrupt it or an error occurs
    while True:
        # Establish connection with client.
        c, addr = s.accept()
        print ('Got connection from', addr )
        try:
            while True:
                data = c.recv(1024)
                if not data:
                    break
            c.send('Thank you for connecting'.encode())
        finally:
            # 确保客户端连接一定会被关闭
            c.close()
except Exception as e:
    print(f"运行时出现错误: {e}")
finally:
    # 确保主socket一定会被关闭
    s.close()

这段代码加了信号处理和try-finally块,不管是正常退出还是意外崩溃,都会把socket关闭,减少端口残留的概率。

最后,聊聊TIME_WAIT状态的问题

如果进程已经完全退出,但还是提示地址被占用,那大概率是端口处于TIME_WAIT状态(TCP协议用来确保数据传输完整的机制,默认会持续2分钟左右)。这时候SO_REUSEADDR应该允许你重新绑定,但有些系统可能需要额外调整参数:
你可以临时开启TCP端口重用:

sudo sysctl -w net.ipv4.tcp_tw_reuse=1

这个命令会让系统允许重用处于TIME_WAIT状态的端口,不过不建议长期修改这个参数,除非你确定你的业务场景需要。如果不想改参数,也可以等个2分钟,端口会自动释放。

按照上面的步骤来,应该就能解决你的问题了!

备注:内容来源于stack exchange,提问作者Peter_Brown_USA

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 17:17:58