Python socket.settimeout() 在连接到已关闭的域时无法正常工作
Python socket.settimeout() not working when connecting to a domain that is down
我需要快速检查主机是启动还是关闭。为此,我在建立连接之前添加了一个套接字超时,但套接字超时似乎不起作用。为什么?
这是我的代码:
import socket
def test_hostname(hostname, port):
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.settimeout(1.0) # timeout
try:
s.connect((hostname, port))
except (socket.timeout, socket.gaierror):
return False
else:
return True
finally:
s.close()
result = test_hostname("001.com",80) # 001.com is down
print(result)
我需要大约 10-20 秒而不是指定的超时(1 秒)。
发生这种情况是因为 Python 套接字的超时 而不是 限制了花在 DNS 查找上的时间。由于您正在使用需要解析为 IP 的域名,因此您的 s.connect((hostname, port))
将首先需要对 hostname
进行 DNS 查询,然后才能使用一个创建连接由 DNS 服务器(如果有)编辑的 IP return。
域 001.com
似乎无法解析任何 IP 地址,因此您的系统可能需要几秒钟才能 return 失败。发生这种情况时,Python 将退出并且连接将失败,但是超时已经过期很久了。
如果您知道要访问的主机的 IP 地址,请使用该地址代替主机名。如果没有,您将不得不使用 DNS 解析库来超时 DNS 解析,例如 dnspython
:
import socket
import dns.resolver
def test_hostname(hostname, port):
resolver = dns.resolver.Resolver()
resolver.timeout = resolver.lifetime = 1
try:
answer = resolver.resolve(hostname, 'A')
except dns.exception.Timeout:
return False
if not answer.rrset:
return False
addr = next(iter(answer.rrset)).to_text()
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(1)
try:
s.connect((addr, port))
except (socket.timeout, socket.gaierror):
return False
else:
return True
finally:
s.close()
我需要快速检查主机是启动还是关闭。为此,我在建立连接之前添加了一个套接字超时,但套接字超时似乎不起作用。为什么?
这是我的代码:
import socket
def test_hostname(hostname, port):
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.settimeout(1.0) # timeout
try:
s.connect((hostname, port))
except (socket.timeout, socket.gaierror):
return False
else:
return True
finally:
s.close()
result = test_hostname("001.com",80) # 001.com is down
print(result)
我需要大约 10-20 秒而不是指定的超时(1 秒)。
发生这种情况是因为 Python 套接字的超时 而不是 限制了花在 DNS 查找上的时间。由于您正在使用需要解析为 IP 的域名,因此您的 s.connect((hostname, port))
将首先需要对 hostname
进行 DNS 查询,然后才能使用一个创建连接由 DNS 服务器(如果有)编辑的 IP return。
域 001.com
似乎无法解析任何 IP 地址,因此您的系统可能需要几秒钟才能 return 失败。发生这种情况时,Python 将退出并且连接将失败,但是超时已经过期很久了。
如果您知道要访问的主机的 IP 地址,请使用该地址代替主机名。如果没有,您将不得不使用 DNS 解析库来超时 DNS 解析,例如 dnspython
:
import socket
import dns.resolver
def test_hostname(hostname, port):
resolver = dns.resolver.Resolver()
resolver.timeout = resolver.lifetime = 1
try:
answer = resolver.resolve(hostname, 'A')
except dns.exception.Timeout:
return False
if not answer.rrset:
return False
addr = next(iter(answer.rrset)).to_text()
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(1)
try:
s.connect((addr, port))
except (socket.timeout, socket.gaierror):
return False
else:
return True
finally:
s.close()