2010-09-21 5 views
80

Я хочу посмотреть, могу ли я получить доступ к онлайн-API, но для этого мне нужен доступ в Интернет.Проверка сетевого подключения

Как я могу узнать, есть ли доступ к подключению и активен с помощью Python?

+0

Если вы находитесь на питоне, это почти наверняка вызовет исключение в случае сбоя подключения или таймаута. Вы можете либо попробовать/поймать это, либо просто дать ему поверхность. – jdizzle

+1

@Triptych: Я надеюсь, что это была шутка, потому что она не работает – inspectorG4dget

+1

@ inspectorG4dget: 'easy_install system_of_tubes' –

ответ

93

Может быть, вы могли бы использовать что-то вроде этого:

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 является один из IP-адресов для google.com. Изменить http://216.58.192.142 на любой сайт можно быстро ответить.

Этот фиксированный IP-адрес не будет отображаться на google.com навсегда. Таким образом, этот код не является надежным - для его работы потребуется постоянное обслуживание.

Причина, по которой указанный выше код использует фиксированный IP-адрес вместо полного доменного имени (FQDN), заключается в том, что для полного доменного имени потребуется поиск DNS. Когда у компьютера нет рабочего интернет-соединения, сам поиск DNS может заблокировать вызов до urllib_request.urlopen более чем на секунду. Спасибо @rzetterberg за это.


Если фиксированный IP-адрес выше не работает, вы можете найти текущий IP-адрес google.com (на Unix), запустив

% dig google.com +trace 
... 
google.com.  300 IN A 216.58.192.142 
+0

спасибо m8, просто, как и он работает очень сильно! :) –

+1

Просто примечание о «вызове' urlopen' займет не больше 1 секунды, даже если интернет не включен ». Это неверно, если указанный URL недействителен, тогда поиск DNS блокируется. Это верно только для фактического подключения к веб-серверу. Самый простой способ избежать этого блока поиска DNS - использовать вместо этого IP-адрес, тогда он гарантированно займет всего 1 секунду :) – rzetterberg

+4

ЭТО НЕ ДОЛЖНО РАБОТАТЬ. По состоянию на сентябрь 2013 года, после долгого времени, http://74.125.113.99 раза, поэтому эта функция всегда будет возвращать False. Я полагаю, что Google изменил свою сеть. – theamk

9

Вы можете просто попытаться загрузить данные, и если соединение не удастся, вы узнаете, что что-то с подключением не очень хорошо.

В принципе, вы не можете проверить, подключен ли компьютер к Интернету. Могут быть много причин для отказа, например неправильная настройка DNS, брандмауэры, NAT. Поэтому, даже если вы сделаете некоторые тесты, вы не можете гарантировать, что у вас будет соединение с вашим API, пока вы не попробуете.

+1

«Легче просить прощения, чем разрешение» – cobbal

+0

Это не должно быть так хорошо. Мне просто нужно попытаться подключиться к сайту или пинговать что-то, и если он даст таймаут voilá. Как я могу это сделать? –

+0

Есть ли причина, по которой вы не можете просто попытаться подключиться к API? Почему вы должны проверить его до реального подключения? –

3

Попробуйте операцию, которую вы пытались сделать в любом случае , Если это не удается, python должен бросить вам исключение, чтобы вы знали.

Чтобы попытаться выполнить некоторую тривиальную операцию, чтобы обнаружить соединение, будет введено условие гонки. Что делать, если интернет-соединение действительно, когда вы проверяете, но уходит, прежде чем вам нужно будет выполнить фактическую работу?

16

Просто обновить то, что unutbu сказал для нового кода в Python 3.2

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

И только отметить, вход здесь (ссылка) является URL, который вы хотите проверить: я предлагаю выбрать что-то, что соединяет быстро, где вы живете, то есть я живу в Южной Корее, поэтому я, вероятно, установил бы ссылку на http://www.naver.com.

12

В качестве альтернативы 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 

Bonus: это может быть продлен до этой функции, которая пингует сайт.

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 
+0

Запрос - отличная библиотека. Однако в отличие от многих примеров здесь я бы использовал [IANA's example.com] (https://www.iana.org/domains/reserved) или example.org как более надежный долгосрочный выбор, поскольку он полностью контролируется [ICANN] (https://en.wikipedia.org/wiki/ICANN). – chirale

31

Будет быстрее просто сделать запрос HEAD, поэтому HTML-код не будет извлечен.
Кроме того, я уверен, что Google хотел бы это лучше так :)

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 
+4

Принимает только 20 миллисекунд, а верхний ответ занимает 1 секунду. – Wally

+3

+1 Нет смысла загружать всю страницу, если вы хотите проверить, доступен ли сервер и что он отвечает. Загрузите контент, если вам нужен контент – thatsIch

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

0

Принимая unutbu's answer в качестве отправной точки, и, были сожжены в прошлом путем «статического» изменения IP-адреса я сделал простой класс, который проверяет один раз с помощью поиска DNS (т. е. используя URL-адрес «https://www.google.com»), а затем сохраняет IP-адрес отвечающего сервера для использования при последующих проверках. Таким образом, IP-адрес всегда обновляется (предполагается, что класс повторно инициализируется не реже одного раза в несколько лет или около того). Я также отдает должное gawry за this answer, который показал мне, как получить IP-адрес сервера (после любого перенаправления и т. Д.). Пожалуйста, не обращайте внимания на кажущуюся хитрость этого решения, я собираюсь привести здесь минимальный рабочий пример. :)

Вот что у меня есть:

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

Если мы можем подключиться к какой-то интернет-сервер, то мы действительно имеем связи. Тем не менее, самый быстрый и самый надежный подход, все решения должны соответствовать следующим требованиям, по крайней мере:

разрешение DNS
  • Избегайте (нам потребуется IP, который хорошо известен и гарантированно будет доступен в большинстве случаев)
  • Избегайте подключений на уровне приложений (подключение к службе HTTP/FTP/IMAP)
  • Избегайте вызовов внешних утилит с Python или другого языка выбора (нам нужно придумать язык-агностик решение, которое не зависит от сторонних решений)

Чтобы соответствовать этим требованиям, можно сделать один подход, проверить, доступен ли один из Google's public DNS servers. Адреса 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 

Как мы можем видеть, TCP/53 открыт и нефильтрованное. Если вы являетесь пользователем, не являющимся пользователем 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 через TCP/53. Теперь мы можем установить соединение через сокет к 8.8.8.8:53/TCP в Python, чтобы проверить подключение:

>>> 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 и т. Д. Прокомментируйте, если вы думаете иначе.

UPDATE # 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 в выводе выше означает, что все эти реализации от соответствующих авторов правильно определить возможность подключения к Интернету. Время отображается с разрешением в миллисекундах.

UPDATE # 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 
+1

Это лучший ответ, избегая разрешения DNS и, по иронии судьбы, консультируясь с DNS-службой Google на порту 53. – erm3nda

+0

kudos для ответа. Brilliant. Просто быстрый вопрос, изменяет ли DNS-сервер google IP? или его фиксированный? –

+1

@AviMehenwal Google предоставляет этот IP-адрес в качестве части бесплатного использования службы разрешения имен DNS. IP-адрес не должен изменяться, если Google не примет иного решения. Я использую его как альтернативный DNS-сервер уже несколько лет без каких-либо проблем. – 7h3rAm

0

Это может не работать, если локальный был изменен с 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-адресом. Надежда, что помогает

+0

Это интересная проверка, хотя она будет определять только если вы подключены к сети. Будет ли это Интернет или подсеть NAT'd, все равно останется вопросом. – 7h3rAm

+0

@ 7h3rAm, это хороший момент, DCHP не требует подключения к интернету, моя ошибка. –

0

мои любимый, при выполнении сценариев на кластере или нет

import subprocess 

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

это работает Wget тихо, ничего не скачивая, но проверять, что данный удаленный файл существует в Интернете

0

Отвечая на шесть ответов, я думаю, что мы могли бы как-то упростить, важный вопрос, поскольку новички теряются в высокотехнических вопросах.

Здесь, что я, наконец, буду использовать, чтобы дождаться, когда мое соединение (3G, медленное) будет установлено один раз в день для моего мониторинга PV.

Работы по Pyth3 с Raspbian 3.4.2

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 минут, если Достигнутые я буду стараться в течение одного часа, но его еще один бит сценария!

+0

Ваш essai var не привыкает, не так ли? – kidCoder

Смежные вопросы