检查网络连接

时间:2010-09-21 20:39:15

标签: python networking

我想知道我是否可以访问在线API,但为此我需要访问Internet。

如何使用Python查看是否存在可用且活动的连接?

21 个答案:

答案 0 :(得分:117)

也许你可以使用这样的东西:

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查找。当机器没有可用的互联网连接时,DNS查找本身可能会阻止对urllib_request.urlopen的呼叫超过一秒钟。感谢@rzetterberg指出这一点。


如果上面的固定IP地址不起作用,您可以通过运行

找到google.com的当前IP地址(在unix上)
% dig google.com  +trace 
...
google.com.     300 IN  A   216.58.192.142

答案 1 :(得分:82)

如果我们可以连接到某个Internet服务器,那么我们确实有连接。但是,对于最快和最可靠的方法,所有解决方案至少应符合以下要求:

  • 避免DNS解析(我们需要一个众所周知并且保证在大多数情况下都可用的IP)
  • 避免基于应用程序层的连接(连接到HTTP / FTP / IMAP服务)
  • 避免从Python或其他选择的语言调用外部实用程序(我们需要提出一种不依赖于第三方解决方案的语言无关的解决方案)。

为了符合这些,一种方法可以是,检查Google's public DNS servers中的一个是否可达。这些服务器的IPv4地址为8.8.8.88.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用户,请记住使用sudo或Nmap的-Pn参数发送精心设计的探测数据包并确定主机是否已启动。

在我们尝试使用Python之前,让我们使用外部工具Netcat测试连接性:

$ 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中设置一个到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探测发送到其中一个服务器并等待响应。但是,我认为,由于数据包丢失,DNS解析失败等原因,它可能会比较慢。如果您不这么认为,请发表评论。

更新#1:感谢@ theamk的评论,超时现在是一个参数,默认情况下初始化为3秒。

更新#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的连接。时间以毫秒分辨率显示。

更新#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 :(得分:50)

发出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

答案 3 :(得分:16)

只是为了更新unutbu在Python 3.2中为新代码所说的内容

def check_connectivity(reference):
    try:
        urllib.request.urlopen(reference, timeout=1)
        return True
    except urllib.request.URLError:
        return False

而且,请注意,此处的输入(参考)是您要检查的网址:我建议选择一些能够快速连接的地方 - 即我住在韩国,所以我可能会参考http://www.naver.com

答案 4 :(得分:16)

作为ubutnu / Kevin C答案的替代方案,我使用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

奖励:这可以扩展到这个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

答案 5 :(得分:9)

您可以尝试下载数据,如果连接失败,您将会知道连接的某些内容并不理想。

基本上您无法检查计算机是否已连接到互联网。失败可能有很多原因,例如错误的DNS配置,防火墙,NAT。因此,即使您进行了一些测试,也无法确保在尝试之前与API建立连接。

答案 6 :(得分:6)

date

对于python 3,请使用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!' )

答案 7 :(得分:3)

尝试您尝试进行的操作。如果失败,python应该抛出一个例外来告诉你。

首先尝试一些简单的操作来检测连接将引入竞争条件。如果互联网连接在您测试时有效但在您需要进行实际工作之前停机怎么办?

答案 8 :(得分:2)

如果已从127.0.0.1更改了localhost,则此操作可能无效 试试

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地址。 希望有所帮助

答案 9 :(得分:1)

我最喜欢的一个,在群集上运行脚本时不是

import subprocess

def online(timeout):
    try:
        return subprocess.run(
            ['wget', '-q', '--spider', 'google.com'],
            timeout=timeout
        ).returncode == 0
    except subprocess.TimeoutExpired:
        return False

这样可以安静地运行wget,不会下载任何内容,只需检查网络上是否存在给定的远程文件

答案 10 :(得分:1)

具有requests的现代便携式解决方案:

import requests

def internet():
    """Detect an internet connection."""

    connection = None
    try:
        r = requests.get("https://google.com")
        r.raise_for_status()
        print("Internet connection detected.")
        connection = True
    except:
        print("Internet connection not detected.")
        connection = False
    finally:
        return connection

或者,一个引发异常的版本:

import requests
from requests.exceptions import ConnectionError

def internet():
    """Detect an internet connection."""

    try:
        r = requests.get("https://google.com")
        r.raise_for_status()
        print("Internet connection detected.")
    except ConnectionError as e:
        print("Internet connection not detected.")
        raise e

答案 11 :(得分:1)

这样做的最佳方法是检查python总是在无法找到网站时提供的IP地址。在这种情况下,这是我的代码:

import socket

print("website connection checker")
while True:
    website = input("please input website: ")
    print("")
    print(socket.gethostbyname(website))
    if socket.gethostbyname(website) == "92.242.140.2":
        print("Website could be experiencing an issue/Doesn't exist")
    else:
        socket.gethostbyname(website)
        print("Website is operational!")
        print("")

答案 12 :(得分:0)

采取六'回答我认为我们可以以某种方式简化,这是一个重要的问题,因为新手在高度技术性的问题上都会丢失。

这里我最终会用来等待我的连接(3G,慢速)每天建立一次我的PV监控。

使用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分钟,我将在一小时的时间内尝试,但它的另一部分脚本!

答案 13 :(得分:0)

接受Ivelin的回答并添加一些额外的检查,因为我的路由器在查询google.com时会提供其ip地址192.168.0.1并返回一个头部(如果它没有互联网连接)。

def haveInternet():
    try:
        # first check if we get the correct IP-Address or just the router's IP-Address
        info = socket.getaddrinfo("www.google.com", None)[0]
        ipAddr = info[4][0]
        if ipAddr == "192.168.0.1" :
            return False
    except:
        return False

    conn = httplib.HTTPConnection("www.google.com", timeout=5)
    try:
        conn.request("HEAD", "/")
        conn.close()
        return True
    except:
        conn.close()
        return False

答案 14 :(得分:0)

  

这是我的版本

import requests

try:
    if requests.get('https://google.com').ok:
        print("You're Online")
except:
    print("You're Offline")

答案 15 :(得分:0)

这在Python3.6中对我有效

import urllib
from urllib.request import urlopen


def is_internet():
    """
    Query internet using python
    :return:
    """
    try:
        urlopen('https://www.google.com', timeout=1)
        return True
    except urllib.error.URLError as Error:
        print(Error)
        return False


if is_internet():
    print("Internet is active")
else:
    print("Internet disconnected")

答案 16 :(得分:0)

unutbu's answer为起点,并且过去因“静态”IP地址更改而被烧毁,我创建了一个简单的类,使用DNS查找检查一次(即使用URL “https://www.google.com”),然后存储响应服务器的IP地址,以便在后续检查中使用。这样,IP地址始终是最新的(假设每隔几年左右重新初始化一次类)。我还对this answer的gawry表示赞赏,它向我展示了如何获取服务器的IP地址(在任何重定向之后等)。请忽略这个解决方案明显的hackiness,我在这里寻找一个最小的工作示例。 :)

这就是我所拥有的:

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()

答案 17 :(得分:0)

我在Joel的代码中添加了一些内容。

    import socket,time
    mem1 = 0
    while True:
        try:
                host = socket.gethostbyname("www.google.com") #Change to personal choice of site
                s = socket.create_connection((host, 80), 2)
                s.close()
                mem2 = 1
                if (mem2 == mem1):
                    pass #Add commands to be executed on every check
                else:
                    mem1 = mem2
                    print ("Internet is working") #Will be executed on state change

        except Exception as e:
                mem2 = 0
                if (mem2 == mem1):
                    pass
                else:
                    mem1 = mem2
                    print ("Internet is down")
        time.sleep(10) #timeInterval for checking

答案 18 :(得分:0)

对于我的项目,我使用script modified来ping谷歌公共DNS服务器8.8.8.8。使用1秒超时和无外部依赖项的核心python库:

class MainWidgetState extends State<MainWidget> {

  @override
  void initState() {
    super.initState();
    this.initDynamicLinks();
  }

  initDynamicLinks(BuildContext context) async {
    await Future.delayed(Duration(seconds: 3));
    var data = await FirebaseDynamicLinks.instance.getInitialLink();
    var deepLink = data?.link;
    final queryParams = deepLink.queryParameters;
    if (queryParams.length > 0) {
      var userName = queryParams['userId'];
      openFormScreen(userName);
    }
    FirebaseDynamicLinks.instance.onLink(onSuccess: (dynamicLink)
    async {
      var deepLink = dynamicLink?.link;
      final queryParams = deepLink.queryParameters;
      if (queryParams.length > 0) {
        var userName = queryParams['userId'];
        openFormScreen(userName);
      }
      debugPrint('DynamicLinks onLink $deepLink');
    }, onError: (e) async {
      debugPrint('DynamicLinks onError $e');
    });
  }

  openFormScreen(String userName){
    Navigator.of(context).pushNamed("routeFormScreen", arguments: {"name": userName});
  }
}

select超时值为1,但是在本示例中,它可以是一个选择的浮点数,它比1秒更容易失败。

答案 19 :(得分:0)

导入请求并尝试使用此简单的python代码。

def check_internet():
    url = 'http://www.google.com/'
    timeout = 5
    try:
        _ = requests.get(url, timeout=timeout)
        return True
    except requests.ConnectionError:
        return False

答案 20 :(得分:0)

通过运行确保您的点子是最新的

BarDataSet barDataSet1 = new BarDataSet(barEntries, "Dataset 1");

使用安装请求包

pip install --upgrade pip
pip install requests