检查networking连接
我想看看我是否可以访问在线API,但为此我需要访问Internet。
我怎样才能看到是否有一个连接可用和使用Python的积极?
也许你可以使用这样的东西:
import urllib2 def internet_on(): try: urllib2.urlopen('http://216.58.192.142', timeout=1) return True except urllib2.URLError as err: return False
目前,216.58.192.142是google.com的IP地址之一。 更改http://216.58.192.142
任何网站可以预期快速回应 。
这个固定的IP永远不会映射到google.com。 所以这个代码是不健壮的 – 它将需要不断的维护,以保持它的工作。
上面的代码使用固定的IP地址而不是完全限定的域名(FQDN)的原因是因为FQDN将需要DNS查找。 当机器没有可用的networking连接时,DNS查找本身可能会阻止对urllib_request.urlopen
的调用超过一秒。 感谢@rzetterberg指出这一点。
如果上面的固定IP地址不起作用,您可以通过运行findgoogle.com(在unix上)的当前IP地址
% dig google.com +trace ... google.com. 300 IN A 216.58.192.142
如果我们可以连接到一些互联网服务器,那么我们确实有连接性。 但是,为了最快和最可靠的方法,所有解决scheme至less应符合以下要求:
- 避免DNSparsing(我们将需要一个知名的IP,并保证大部分时间都可用)
- 避免基于应用层的连接(连接到HTTP / FTP / IMAP服务)
- 避免从Python或其他select的语言中调用外部实用程序(我们需要提出一个不依赖于第三方解决scheme的与语言无关的解决scheme)
为了遵守这些规定,一种方法可能是,检查一个Google的公共DNS服务器是否可以访问。 这些服务器的IPv4地址是8.8.8.8
和8.8.4.4
。 我们可以尝试连接到他们中的任何一个。
主机8.8.8.8
快速Nmap给出如下结果:
$ 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
正如我们所看到的,TCP / 53是开放的,没有被过滤。 如果您是非root用户,请记住为Nmap使用sudo
或-Pn
参数发送制作的探测包,并确定主机是否启动。
在我们尝试使用Python之前,让我们使用一个外部工具Netcattesting连通性:
$ nc 8.8.8.8 53 -zv Connection to 8.8.8.8 53 port [tcp/domain] succeeded!
Netcat证实我们可以通过TCP / 53达到8.8.8.8
。 现在我们可以在Python中build立一个到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 Exception as ex: ... print ex.message ... return False ... >>> internet() True >>>
另一种方法可能是将手动制作的DNS探测器发送到其中一台服务器,然后等待响应。 但是,我认为,由于数据包丢失,DNSparsing失败等原因,这可能会比较慢。请您评论一下,否则。
更新#1:感谢@ theamk的评论,超时现在是一个参数,并默认初始化为3秒。
更新#2:我做了快速testing,以确定这个问题的所有有效答案的最快和最通用的实现。 这里是总结:
$ 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
在上面的输出中是正确的,表示来自各个作者的所有这些实现正确地标识了与Internet的连接。 时间以毫秒分辨率显示。
更新#3:exception处理更改后再次testing:
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
只是做一个HEAD请求会更快,所以不会提取HTML。
此外,我相信谷歌会更喜欢这种方式:)
try: import httplib except: import http.client as httplib def have_internet(): conn = httplib.HTTPConnection("www.google.com", timeout=5) try: conn.request("HEAD", "/") conn.close() return True except: conn.close() return False
只是为了更新Python 3.2中的新代码的unutbu说
def check_connectivity(reference): try: urllib.request.urlopen(reference, timeout=1) return True except urllib.request.URLError: return False
而且,要注意的是,这里的input(reference)是你想要检查的url:我build议你select一个能够快速连接你的地方的东西,也就是我住在韩国,所以我可能会设置引用http:/ /www.naver.com 。
作为ubutnu / Kevin C答案的替代scheme,我使用如下的requests
包:
import requests def connected_to_internet(url='http://www.google.com/', timeout=5): try: _ = requests.get(url, timeout=timeout) return True except requests.ConnectionError: print("No internet connection available.") return False
奖金:这可以扩展到这个function,ping一个网站。
def web_site_online(url='http://www.google.com/', timeout=5): try: req = requests.get(url, timeout=timeout) # HTTP errors are not raised by default, this statement does that req.raise_for_status() return True except requests.HTTPError as e: print("Checking internet connection failed, status code {0}.".format( e.response.status_code)) except requests.ConnectionError: print("No internet connection available.") return False
你可以尝试下载数据,如果连接失败,你会知道连接的东西不好。
基本上你不能检查电脑是否连接到互联网。 可能有很多原因导致失败,比如错误的DNSconfiguration,防火墙,NAT。 所以即使你做了一些testing,你也不能保证在你尝试之前你会连接到你的API。
试试你正在尝试做的操作。 如果它失败,python应该抛出一个exception让你知道。
首先尝试一些微不足道的操作来检测连接将引入一个竞争条件。 如果在testing时互联网连接是有效的,但是在你需要做实际的工作之前会下降呢?
import urllib def connected(host='http://google.com'): try: urllib.urlopen(host) return True except: return False # test print( 'connected' if connected() else 'no internet!' )
对于python 3,使用urllib.request.urlopen(host)
以unutbu的答案为起点,并通过“静态”IP地址改变过去,我做了一个简单的类,使用DNS查找(即使用URL“ https:// www .google.com “),然后存储响应服务器的IP地址以供后续检查使用。 这样,IP地址始终是最新的(假定每隔几年左右至less重新初始化一次)。 我也赞同gawry 这个答案 ,它告诉我如何得到服务器的IP地址(在任何redirect之后等)。 请忽略这个解决scheme的显而易见的弊端,我要在这里做个简单的例子。 🙂
这是我有什么:
import socket try: from urllib2 import urlopen, URLError from urlparse import urlparse except ImportError: # Python 3 from urllib.parse import urlparse from urllib.request import urlopen, URLError class InternetChecker(object): conn_url = 'https://www.google.com/' def __init__(self): pass def test_internet(self): try: data = urlopen(self.conn_url, timeout=5) except URLError: return False try: host = data.fp._sock.fp._sock.getpeername() except AttributeError: # Python 3 host = data.fp.raw._sock.getpeername() # Ensure conn_url is an IPv4 address otherwise future queries will fail self.conn_url = 'http://' + (host[0] if len(host) == 2 else socket.gethostbyname(urlparse(data.geturl()).hostname)) return True # Usage example checker = InternetChecker() checker.test_internet()
如果本地主机已从127.0.0.1
尝试更改,这可能无法正常工作
import socket ipaddress=socket.gethostbyname(socket.gethostname()) if ipaddress=="127.0.0.1": print("You are not connected to the internet!") else: print("You are connected to the internet with the IP address of "+ ipaddress )
未经编辑,您的计算机IP在未连接到互联网时将为127.0.0.1。 这段代码基本上获取IP地址,然后询问是否是本地主机IP地址。 希望有所帮助
以六个答案为例,我认为我们可以简化一下,这是一个重要的问题,因为在高度技术性的问题上失去了新手。
在这里,我最终将用我的等待我的连接(3G,慢)来build立我的光伏监控一天一次。
使用Raspbian 3.4.2在Pyth3下运行
from urllib.request import urlopen from time import sleep urltotest=http://www.lsdx.eu # my own web page nboftrials=0 answer='NO' while answer=='NO' and nboftrials<10: try: urlopen(urltotest) answer='YES' except: essai='NO' nboftrials+=1 sleep(30)
最大跑步:5分钟,如果达到我会尝试在一个小时的时间,但它的另一个脚本!
我最喜欢的一个,当在群集上运行脚本或不
import subprocess def online(timeout): try: return subprocess.run(['wget', '-q', '--spider', 'google.com'], timeout=timeout).returncode == 0 except subprocess.TimeoutExpired: return False
这安静地运行wget,没有下载任何东西,只是检查给定的远程文件存在于networking上