Memeriksa koneksi jaringan


133

Saya ingin melihat apakah saya dapat mengakses API online, tetapi untuk itu saya perlu memiliki akses Internet.

Bagaimana saya bisa melihat apakah ada koneksi yang tersedia dan aktif menggunakan Python?


jika Anda menggunakan python, itu hampir pasti akan membuang pengecualian jika terjadi kegagalan koneksi atau batas waktu. Anda bisa mencoba / menangkapnya, atau membiarkannya muncul.
jdizzle

1
@Triptych: Saya harap itu hanya lelucon, karena tidak berfungsi
inspectorG4dget

1
@ inspectorG4dget:easy_install system_of_tubes
S.Lott

2
@ aF: Lihat solusi Unutbu. Ini menunjukkan (dengan cara tercepat mungkin) cara memeriksa apakah Anda dapat mengakses google.com. Jika masalah Anda menyangkut mengakses API, lalu mengapa tidak mencoba mengaksesnya, menetapkan batas waktu = 1? Itu akan memberi tahu Anda dengan tepat jika API yang ingin Anda akses dapat diakses. Setelah Anda mengetahuinya, maka Anda dapat melanjutkan dan mengakses API atau menunggu saat Anda dapat mengaksesnya.
inspectorG4dget

Seperti yang saya katakan, saya hanya perlu hal sederhana seperti kata unutbu. Anda tidak perlu membuat keributan dengan ini ..
aF.

Jawaban:


132

Mungkin Anda bisa menggunakan sesuatu seperti ini:

import urllib2

def internet_on():
    try:
        urllib2.urlopen('http://216.58.192.142', timeout=1)
        return True
    except urllib2.URLError as err: 
        return False

Saat ini, 216.58.192.142 adalah salah satu alamat IP untuk google.com. Ubah http://216.58.192.142ke situs apa pun yang diharapkan dapat merespons dengan cepat .

IP tetap ini tidak akan memetakan ke google.com selamanya. Jadi kode ini tidak kuat - akan membutuhkan pemeliharaan konstan agar tetap berfungsi.

Alasan mengapa kode di atas menggunakan alamat IP tetap alih-alih nama domain yang memenuhi syarat (FQDN) adalah karena FQDN akan membutuhkan pencarian DNS. Ketika mesin tidak memiliki koneksi internet yang berfungsi, pencarian DNS itu sendiri dapat memblokir panggilan ke urllib_request.urlopenlebih dari satu detik. Terima kasih kepada @rzetterberg karena menunjukkan ini.


Jika alamat IP tetap di atas tidak berfungsi, Anda dapat menemukan alamat IP saat ini untuk google.com (di unix) dengan menjalankan

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

1
Hanya catatan pada "panggilan untuk urlopentidak akan memakan waktu lebih lama dari 1 detik bahkan jika internet tidak" pada "." - kutipan. Ini tidak benar jika url yang diberikan tidak valid, maka pencarian DNS akan diblokir. Itu hanya berlaku untuk koneksi aktual ke server web. Cara paling sederhana untuk menghindari blok lookup DNS ini adalah dengan menggunakan IP-adress sebagai gantinya, maka dijamin hanya membutuhkan waktu 1 detik :)
rzetterberg

8
INI TIDAK BEKERJA LAGI. Pada Sep 2013, 74.125.113.99 kali keluar setelah waktu yang lama, jadi fungsi ini akan selalu mengembalikan False. Saya kira Google telah mengubah jaringan mereka sudah diatur.
theamk

4
Sekarang sisanya sederhana. Google untuk "74.125.113.99 urllib". Ini akan mengembalikan ribuan proyek sumber terbuka yang memasukkan kode yang salah. (bagi saya, hanya halaman pertama yang berisi setidaknya 5: nvpy, sweekychebot, malteseDict, upy, checkConnection). Mereka semua hancur sekarang.
theamk

4
Jika tidak jelas, saya TIDAK MENYARANKAN menggunakan metode ini. IP lama baik untuk kurang dari 3 tahun. IP baru berfungsi hari ini. Masukkan ke dalam proyek Anda, dan itu mungkin akan hancur secara misterius dalam waktu kurang dari 3 tahun, lagi.
theamk

1
Er ... buka saja http://google.comlalu Anda selesaikan semua masalah yang semua orang bicarakan di sini. Tidak perlu menggunakan alamat ip ...
Jason C

106

Jika kita dapat terhubung ke beberapa server Internet, maka kita memang memiliki konektivitas. Namun, untuk pendekatan tercepat dan paling dapat diandalkan, semua solusi harus memenuhi persyaratan berikut, paling tidak:

  • Hindari resolusi DNS (kami akan membutuhkan IP yang terkenal dan dijamin tersedia untuk sebagian besar waktu)
  • Hindari koneksi lapisan aplikasi (menghubungkan ke layanan HTTP / FTP / IMAP)
  • Hindari panggilan ke utilitas eksternal dari Python atau bahasa pilihan lain (kita perlu menemukan solusi agnostik bahasa yang tidak bergantung pada solusi pihak ketiga)

Untuk mematuhinya, satu pendekatan bisa jadi, periksa apakah salah satu server DNS publik Google dapat dijangkau. Alamat IPv4 untuk server ini adalah 8.8.8.8dan 8.8.4.4. Kami dapat mencoba menghubungkan ke salah satu dari mereka.

Nmap cepat dari tuan rumah 8.8.8.8memberikan hasil di bawah ini:

$ 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

Seperti yang dapat kita lihat, 53/tcpterbuka dan tidak disaring. Jika Anda adalah pengguna non-root, ingatlah untuk menggunakan sudoatau -Pnargumen untuk Nmap untuk mengirim paket probe buatan dan menentukan apakah sebuah host sudah habis.

Sebelum kita mencoba dengan Python, mari kita uji konektivitas menggunakan alat eksternal, Netcat:

$ nc 8.8.8.8 53 -zv
Connection to 8.8.8.8 53 port [tcp/domain] succeeded!

Menegaskan netcat bahwa kita dapat mencapai 8.8.8.8lebih 53/tcp. Sekarang kita dapat mengatur koneksi socket ke 8.8.8.8:53/tcpdalam Python untuk memeriksa koneksi:

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

Pendekatan lain bisa dengan mengirim probe DNS yang dibuat secara manual ke salah satu server ini dan menunggu jawaban. Tapi, saya berasumsi, ini mungkin terbukti lebih lambat dibandingkan dengan penurunan paket, kegagalan resolusi DNS, dll. Berikan komentar jika Anda berpikir sebaliknya.

UPDATE # 1: Berkat komentar @ theamk, batas waktu sekarang menjadi argumen dan diinisialisasi 3ssecara default.

UPDATE # 2: Saya melakukan tes cepat untuk mengidentifikasi implementasi tercepat dan paling umum dari semua jawaban yang valid untuk pertanyaan ini. Berikut ringkasannya:

$ 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

Dan sekali lagi:

$ 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

Truedalam output di atas menandakan bahwa semua implementasi dari masing-masing penulis dengan benar mengidentifikasi konektivitas ke Internet. Waktu ditunjukkan dengan resolusi milidetik.

UPDATE # 3: Diuji lagi setelah pengecualian menangani perubahan:

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

6
Ini adalah jawaban terbaik, menghindari resolusi DNS, dan ironisnya, berkonsultasi dengan layanan DNS Google di port 53.
m3nda

1
@AviMehenwal Google menyediakan IP ini sebagai bagian dari kebebasannya untuk menggunakan layanan resolusi nama DNS. IP tidak seharusnya berubah kecuali Google memutuskan sebaliknya. Saya telah menggunakannya sebagai server DNS alternatif selama beberapa tahun sekarang tanpa masalah.
7h3rAm

1
@ Lukas Terima kasih telah menunjukkan itu. Saya telah memperbarui jawaban untuk memberi tahu pengguna tentang pengecualian dan mengembalikan False sebagai jawaban default.
7h3rAm

2
@JasonC Menghubungkan ke TCP / 53 berbeda dari koneksi DNS melalui port 53. Dengan analogi Anda, setiap port TCP yang digunakan oleh suatu aplikasi akan diklasifikasikan sebagai koneksi protokol level aplikasi. Tidak itu tidak benar. Menghubungkan melalui soket TCP ke port TIDAK koneksi tingkat aplikasi. Saya tidak melakukan pencarian DNS, melainkan hanya jabat tangan setengah-TCP. Ini tidak sama dengan melakukan pencarian DNS penuh.
7h3rAm

2
Bukankah seharusnya kita memanggil close()soket?
brk

60

Akan lebih cepat untuk hanya membuat permintaan KEPALA sehingga tidak ada HTML yang akan diambil.
Juga saya yakin google akan lebih suka cara ini :)

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

8
Hanya memakan waktu 20 mili detik sedangkan jawaban teratas membutuhkan waktu 1 detik.
Wally

8
+1 Tidak masuk akal untuk mengunduh seluruh halaman jika Anda hanya ingin memeriksa apakah server dapat dijangkau dan merespons. Unduh konten jika Anda membutuhkan konten
thatsIch

Tanpa alasan, menggunakan url '8.8' masih berfungsi, yang jelas, '8.8' atau ' 8.8 ' tidak berfungsi di peramban web asli.
Polv

2 jam mencari solusi yang berhasil dan kemudian saya menemukan ini ... bersih dan sederhana
Pedro Serpa

21

Sebagai alternatif untuk jawaban ubutnu / Kevin C, saya menggunakan requestspaket seperti ini:

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: ini dapat diperluas ke fungsi ini yang mem-ping sebuah situs web.

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

1
Permintaan adalah perpustakaan yang bagus. Namun tidak seperti banyak contoh di sini saya akan menggunakan IANA's example.com atau example.org sebagai pilihan jangka panjang yang lebih andal karena sepenuhnya dikendalikan oleh ICANN .
chirale

Apakah ada cara lain untuk memeriksa status menjalankan internet. Karena jika Anda menyematkan google.comlagi, maka mereka akan memblokir IP kami. Jadi, apakah ada cara lain.?
Sanjiv

15

Hanya untuk memperbarui apa yang dikatakan unutbu untuk kode baru dalam Python 3.2

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

Dan, untuk dicatat, input di sini (referensi) adalah url yang ingin Anda periksa: Saya sarankan memilih sesuatu yang menghubungkan cepat tempat Anda tinggal - yaitu saya tinggal di Korea Selatan, jadi saya mungkin akan menetapkan referensi ke http: / /www.naver.com .


Saya akan menunggu 30 detik jika tidak ada server DNS yang tersedia.
Viktor Joras

10

Anda bisa mencoba mengunduh data, dan jika koneksi gagal, Anda akan tahu bahwa sesuatu dengan koneksi tidak baik.

Pada dasarnya Anda tidak dapat memeriksa apakah komputer terhubung ke internet. Mungkin ada banyak alasan kegagalan, seperti konfigurasi DNS yang salah, firewall, NAT. Jadi, bahkan jika Anda melakukan beberapa tes, Anda tidak dapat menjamin bahwa Anda akan memiliki koneksi dengan API Anda sampai Anda mencobanya.


2
"Lebih mudah untuk meminta pengampunan daripada izin"
cobbal

ini tidak harus sebagus itu. Saya hanya perlu mencoba untuk terhubung ke suatu situs atau melakukan ping sesuatu dan jika itu memberikan waktu habis voilá. Bagaimana saya bisa melakukan itu?
aF.

Apakah ada alasan Anda tidak bisa hanya mencoba terhubung ke API? Mengapa Anda harus memeriksanya sebelum koneksi nyata?
Tomasz Wysocki

Saya membuat halaman html menggunakan python. Halaman html bergantung pada argumen yang saya berikan dalam program python. Saya hanya perlu memasukkan beberapa kode html jika saya dapat mengakses api. Itu sebabnya saya perlu tahu sebelumnya.
aF.

6
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!' )

Untuk python 3, gunakan urllib.request.urlopen(host)


4

Coba operasi yang Anda coba lakukan. Jika gagal, python harus memberi Anda pengecualian untuk memberi tahu Anda.

Untuk mencoba beberapa operasi sepele terlebih dahulu untuk mendeteksi koneksi akan memperkenalkan kondisi balapan. Bagaimana jika koneksi internet valid ketika Anda menguji tetapi turun sebelum Anda perlu melakukan pekerjaan yang sebenarnya?


3

Ini mungkin tidak berfungsi jika localhost telah diubah dari 127.0.0.1 Coba

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 )

Kecuali diedit, IP komputer Anda akan menjadi 127.0.0.1 saat tidak terhubung ke internet. Kode ini pada dasarnya mendapatkan alamat IP dan kemudian bertanya apakah itu adalah alamat IP localhost. Semoga itu bisa membantu


Itu pemeriksaan yang menarik, meskipun hanya akan mengidentifikasi jika Anda terhubung ke jaringan. Apakah itu Internet atau subnet NAT'd masih akan tetap menjadi pertanyaan.
7h3rAm

@ 7h3rAm, itu poin bagus, DCHP tidak memerlukan koneksi internet, kesalahan saya.

Ini hanya membutuhkan koneksi NIC jaringan yang telah menerima IP yang ditetapkan. Tidak seperti semua jawaban lain, itu tidak memerlukan koneksi ke LAN, router, firewall, ISP sampai ke sistem lain. Masih gagal untuk menunjukkan bahwa NIC terhubung jika itu bukan alamat yang ditetapkan DHCP (statis)
user150471

@ user150471, sudah ditunjukkan, terima kasih atas kontribusi Anda.

3

Ini versiku

import requests

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

1
Saya suka yang ini, tetapi akan lebih baik jika dikecualikan dari Timeout atau Koneksi Error tertentu yang muncul dari permintaan. Seperti, Ctrl-C kilat akan mencetak offline.
user2561747

2

Solusi portabel modern dengan 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

Atau, versi yang memunculkan pengecualian:

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

1

Cara terbaik untuk melakukan ini adalah membuatnya mengecek alamat IP yang selalu diberikan python jika tidak dapat menemukan situs web. Dalam hal ini, ini adalah kode saya:

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

1

favorit saya, saat menjalankan skrip pada sebuah cluster atau tidak

import subprocess

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

ini berjalan dengan tenang, tidak mengunduh apa pun kecuali memeriksa apakah file jarak jauh yang diberikan ada di web


0

Mengambil jawaban unutbu sebagai titik awal, dan telah dibakar di masa lalu oleh perubahan alamat IP "statis", saya telah membuat kelas sederhana yang memeriksa sekali menggunakan pencarian DNS (yaitu, menggunakan URL " https: // www .google.com "), lalu menyimpan alamat IP dari server yang merespons untuk digunakan pada pemeriksaan selanjutnya. Dengan begitu, alamat IP selalu terkini (dengan asumsi kelas diinisialisasi ulang setidaknya sekali setiap beberapa tahun atau lebih). Saya juga memberikan pujian kepada jawaban ini , yang menunjukkan kepada saya bagaimana cara mendapatkan alamat IP server (setelah pengalihan, dll.). Harap abaikan kekonyolan dari solusi ini, saya akan mencoba contoh yang minimal di sini. :)

Inilah yang saya miliki:

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

0

Mengambil jawaban Enam, saya pikir kita bisa menyederhanakan entah bagaimana, masalah penting karena pendatang baru hilang dalam masalah yang sangat teknis.

Di sini, apa yang akhirnya akan saya gunakan untuk menunggu koneksi saya (3G, lambat) dibuat sekali sehari untuk pemantauan PV saya.

Bekerja di bawah Pyth3 dengan 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)       

maksimum berjalan: 5 menit jika tercapai saya akan mencoba dalam waktu satu jam tetapi sedikit script lain!


essai var Anda tidak terbiasa, bukan?
kidCoder

0

Mengambil jawaban Ivelin dan menambahkan beberapa pemeriksaan tambahan karena router saya memberikan alamat ip 192.168.0.1 dan mengembalikan kepala jika tidak memiliki koneksi internet saat menanyakan google.com.

import socket

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

0

Ini berfungsi untuk saya di 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")

0

Saya menambahkan beberapa ke kode 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

0

Untuk proyek saya, saya menggunakan skrip yang dimodifikasi untuk melakukan ping ke server DNS publik google 8.8.8.8. Menggunakan batas waktu 1 detik dan pustaka python inti tanpa ketergantungan eksternal:

import struct
import socket
import select


def send_one_ping(to='8.8.8.8'):
   ping_socket = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.getprotobyname('icmp'))
   checksum = 49410
   header = struct.pack('!BBHHH', 8, 0, checksum, 0x123, 1)
   data = b'BCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwx'
   header = struct.pack(
      '!BBHHH', 8, 0, checksum, 0x123, 1
   )
   packet = header + data
   ping_socket.sendto(packet, (to, 1))
   inputready, _, _ = select.select([ping_socket], [], [], 1.0)
   if inputready == []:
      raise Exception('No internet') ## or return False
   _, address = ping_socket.recvfrom(2048)
   print(address) ## or return True


send_one_ping()

Nilai batas waktu pilih adalah 1, tetapi bisa menjadi angka pilihan floating point untuk gagal lebih mudah daripada 1 detik dalam contoh ini.


0

impor permintaan dan coba kode python sederhana ini.

def check_internet():
url = 'http://www.google.com/'
timeout = 5
try:
    _ = requests.get(url, timeout=timeout)
    return True
except requests.ConnectionError:
return False
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.