📅  最后修改于: 2023-12-03 15:27:15.982000             🧑  作者: Mango
当你在编写网络相关的程序时,你可能会遇到 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
可以在 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}")
以上就是可能的解决方法,根据具体情况选择合适的方法。