📜  监听 tcp 127.0.0.1:8001: bind: address already in use - 不管(1)

📅  最后修改于: 2023-12-03 15:27:15.982000             🧑  作者: Mango

监听 TCP 127.0.0.1:8001: bind: address already in use - 不管

当你在编写网络相关的程序时,你可能会遇到 bind 函数绑定套接字到指定地址或端口失败的情况,且错误信息为 address already in use,这时候就需要做一些调试工作了。

这个问题可能是由于前一次程序没有正确关闭的导致的,或者是其他进程正在使用相同的地址和端口。下面是几种可能的解决方法:

杀掉占用该端口的进程

可以通过 lsof 或者 netstat 命令来查找占用该端口的进程,然后使用 kill 命令杀掉进程。

# 查找占用 8001 端口的进程
lsof -i :8001

# 结果中找到进程号,使用 kill 杀掉
kill <pid>
# 查找占用 8001 端口的进程
netstat -nlp | grep 8001

# 结果中找到进程号,使用 kill 杀掉
kill <pid>
等待套接字释放

如果不想修改启动程序的配置,可以等待一段时间让系统自动回收该端口的套接字,通常需要等待 1-2 分钟左右。

import time
import socket

HOST = 'localhost'
PORT = 8001

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
while True:
    try:
        s.bind((HOST, PORT))
        print(f"Server started successfully on {HOST}:{PORT}")
        break
    except socket.error as e:
        print(f"Failed to start server on {HOST}:{PORT}, retrying...")
        time.sleep(5)

s.listen(1)
connection, address = s.accept()
print(f"Connected by {address}")
修改套接字选项

如果前一次程序没有正确关闭,可能导致该端口的套接字处于 TIME_WAIT 状态,这时候需要修改系统的套接字选项来缩短 TIME_WAIT 的时间。

# 查看当前系统中的套接字选项
sudo sysctl net.ipv4.tcp_fin_timeout

# 修改套接字选项,将 TIME_WAIT 时间设置为 30 秒
sudo sysctl -w net.ipv4.tcp_fin_timeout=30
使用SO_REUSEADDR选项

可以在 socket 对象的 setsockopt 方法中设置 SO_REUSEADDR 选项,来允许在端口处于 TIME_WAIT 状态时,重用该地址和端口。

import socket

HOST = 'localhost'
PORT = 8001

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((HOST, PORT))
s.listen(1)
connection, address = s.accept()
print(f"Connected by {address}")

以上就是可能的解决方法,根据具体情况选择合适的方法。