我想看看我是否可以访问在线 API,但为此,我需要能够访问 Internet。
我如何使用 Python 查看是否有连接可用且处于活动状态?
原文由 aF. 发布,翻译遵循 CC BY-SA 4.0 许可协议
我想看看我是否可以访问在线 API,但为此,我需要能够访问 Internet。
我如何使用 Python 查看是否有连接可用且处于活动状态?
原文由 aF. 发布,翻译遵循 CC BY-SA 4.0 许可协议
如果我们可以连接到某个 Internet 服务器,那么我们确实可以连接。然而,为了获得最快和最可靠的方法,所有解决方案至少应符合以下要求:
为了遵守这些规定,一种方法可能是检查是否可以访问 Google 的公共 DNS 服务器 之一。这些服务器的 IPv4 地址是 8.8.8.8
和 8.8.4.4
。我们可以尝试连接到其中任何一个。
主机的快速 Nmap 8.8.8.8
给出了以下结果:
$ sudo nmap 8.8.8.8
Starting Nmap 6.40 ( http://nmap.org ) at 2015-10-14 10:17 IST
Nmap scan report for google-public-dns-a.google.com (8.8.8.8)
Host is up (0.0048s latency).
Not shown: 999 filtered ports
PORT STATE SERVICE
53/tcp open domain
Nmap done: 1 IP address (1 host up) scanned in 23.81 seconds
如我们所见, 53/tcp
是开放的且未过滤。如果您是非 root 用户,请记住使用 sudo
或 -Pn
参数让 Nmap 发送精心制作的探测数据包并确定主机是否启动。
在尝试使用 Python 之前,让我们使用外部工具 Netcat 测试连接性:
$ nc 8.8.8.8 53 -zv
Connection to 8.8.8.8 53 port [tcp/domain] succeeded!
Netcat 确认我们可以到达 8.8.8.8
超过 53/tcp
。现在我们可以在 Python 中建立一个到 8.8.8.8:53/tcp
的套接字连接来检查连接:
import socket
def internet(host="8.8.8.8", port=53, timeout=3):
"""
Host: 8.8.8.8 (google-public-dns-a.google.com)
OpenPort: 53/tcp
Service: domain (DNS/TCP)
"""
try:
socket.setdefaulttimeout(timeout)
socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect((host, port))
return True
except socket.error as ex:
print(ex)
return False
internet()
另一种方法可能是将手动制作的 DNS 探测发送到其中一个服务器并等待响应。但是,我认为,由于数据包丢失、DNS 解析失败等原因,它可能比较慢。如果您有其他想法,请发表评论。
更新 #4: 这个 公共名称服务器列表是 IP 测试的一个很好的参考。
更新 #3:异常处理更改后再次测试:
defos.py
True
00:00:00:00.410
iamaziz.py
True
00:00:00:00.240
ivelin.py
True
00:00:00:00.109
jaredb.py
True
00:00:00:00.520
kevinc.py
True
00:00:00:00.317
unutbu.py
True
00:00:00:00.436
7h3rAm.py
True
00:00:00:00.030
更新#2:我进行了快速测试以确定该问题所有有效答案的最快和最通用的实现。这是摘要:
$ ls *.py | sort -n | xargs -I % sh -c 'echo %; ./timeit.sh %; echo'
defos.py
True
00:00:00:00.487
iamaziz.py
True
00:00:00:00.335
ivelin.py
True
00:00:00:00.105
jaredb.py
True
00:00:00:00.533
kevinc.py
True
00:00:00:00.295
unutbu.py
True
00:00:00:00.546
7h3rAm.py
True
00:00:00:00.032
再一次:
$ ls *.py | sort -n | xargs -I % sh -c 'echo %; ./timeit.sh %; echo'
defos.py
True
00:00:00:00.450
iamaziz.py
True
00:00:00:00.358
ivelin.py
True
00:00:00:00.099
jaredb.py
True
00:00:00:00.585
kevinc.py
True
00:00:00:00.492
unutbu.py
True
00:00:00:00.485
7h3rAm.py
True
00:00:00:00.035
True
在上面的输出中表示来自各个作者的所有这些实现都正确地识别了到 Internet 的连接。时间以毫秒分辨率显示。
更新 #1:感谢 @theamk 的评论,超时现在是一个参数并默认初始化为 3s
。
原文由 7h3rAm 发布,翻译遵循 CC BY-SA 4.0 许可协议
2 回答5.2k 阅读✓ 已解决
2 回答1.1k 阅读✓ 已解决
4 回答1.4k 阅读✓ 已解决
3 回答1.3k 阅读✓ 已解决
3 回答1.3k 阅读✓ 已解决
2 回答884 阅读✓ 已解决
1 回答1.8k 阅读✓ 已解决
也许你可以使用这样的东西:
目前,216.58.192.142 是 google.com 的 IP 地址之一。 _将
http://216.58.192.142
更改为可以快速响应的任何站点_。这个固定 IP 永远不会映射到 google.com。所以这段代码并不健壮——它需要不断维护才能保持运行。
上面的代码使用固定 IP 地址而不是完全限定域名 (FQDN) 的原因是因为 FQDN 需要 DNS 查找。当机器没有可用的互联网连接时,DNS 查找本身可能会阻止对
urllib_request.urlopen
的调用超过一秒钟。感谢@rzetterberg 指出这一点。如果上面的固定 IP 地址不起作用,您可以通过运行找到 google.com(在 unix 上)的当前 IP 地址