네트워크 연결 확인


133

온라인 API에 액세스 할 수 있는지 확인하고 싶지만 인터넷에 액세스해야합니다.

파이썬을 사용하여 연결이 가능하고 활성화되어 있는지 어떻게 알 수 있습니까?


파이썬이라면 연결 실패 또는 시간 초과가 발생했을 때 예외가 발생합니다. 그 주위를 시도 / 잡거나 표면에 놓을 수 있습니다.
jdizzle

1
@Triptych : 그것은 작동하지 않기 때문에 나는 그 농담 희망
inspectorG4dget

1
@ inspectorG4dget :easy_install system_of_tubes
S.Lott

2
@aF : Unutbu의 솔루션을보십시오. google.com에 액세스 할 수 있는지 확인하는 방법을 가장 빠른 방법으로 보여줍니다. API에 액세스하는 데 문제가있는 경우 timeout = 1로 설정하여 액세스하지 않는 이유는 무엇입니까? 액세스하려는 API에 액세스 할 수 있는지 정확하게 알려줍니다. 일단 알고 나면 API에 액세스하거나 API에 액세스 할 수있을 때까지 기다릴 수 있습니다.
inspectorG4dget 1

내가 말했듯이, 나는 unutbu가 말한 것처럼 간단한 것이 필요했습니다. 이런 소란을 피우지 않아도됩니다 ..
aF.

답변:


132

아마도 당신은 다음과 같은 것을 사용할 수 있습니다 :

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에 영원히 매핑되지 않습니다. 따라서이 코드는 강력하지 않습니다. 계속 작동하려면 지속적인 유지 관리가 필요합니다.

위 코드에서 FQDN (정규화 된 도메인 이름) 대신 고정 IP 주소를 사용하는 이유는 FQDN에 DNS 조회가 필요하기 때문입니다. 컴퓨터가 인터넷에 연결되어 있지 않으면 DNS 조회 자체가 urllib_request.urlopen1 초 이상 통화를 차단할 수 있습니다 . 이것을 지적 해준 @rzetterberg에게 감사합니다.


위의 고정 IP 주소가 작동하지 않으면 다음을 실행하여 google.com (unix)의 현재 IP 주소를 찾을 수 있습니다.

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

1
" urlopen인터넷이"켜져 있지 않은 경우에도 호출 시간이 1 초 이상 걸리지 않습니다. " 제공된 URL이 유효하지 않으면 DNS 조회가 차단됩니다. 웹 서버에 실제로 연결하는 경우에만 해당됩니다. 이 DNS 조회 블록을 회피하는 가장 간단한 방법은 :) 단 1 초 걸릴 대신 다음을 보장 년대 IP-ADRESS을 사용하는 것입니다
rzetterberg

8
더 이상 작동하지 않습니다. 2013 년 9 월부터 오랜 시간이 지나면 74.125.113.99가 시간 초과 되므로이 함수는 항상 False를 반환합니다. Google이 네트워크 설정을 변경했다고 가정합니다.
theamk

4
이제 나머지는 간단합니다. "74.125.113.99 urllib"에 대한 Google. 잘못된 코드를 통합 한 수천 개의 오픈 소스 프로젝트를 반환합니다. (나의 경우 첫 번째 페이지에만 5 이상이 있습니다 : nvpy, sweekychebot, malteseDict, upy, checkConnection). 그들은 이제 모두 부서졌습니다.
theamk

4
명확하지 않으면이 방법을 사용하지 않는 것이 좋습니다. 오래된 IP는 3 년 미만 동안 좋았습니다. 새로운 IP가 오늘 작동합니다. 프로젝트에 넣으면 3 년 안에 다시는 깨질 수 있습니다.
theamk

1
어 .. 그냥 열면 http://google.com모든 사람들이 여기서 계속 이야기하는 모든 문제를 해결할 수 있습니다. IP 주소를 사용할 필요가 없습니다 ...
Jason C

106

인터넷 서버에 연결할 수 있다면 실제로 연결되어있는 것입니다. 그러나 가장 빠르고 가장 안정적인 방법을 사용하려면 모든 솔루션이 최소한 다음 요구 사항을 준수해야합니다.

  • DNS 확인을 피하십시오 (우리는 잘 알려져 있고 대부분의 시간 동안 사용 가능한 IP가 필요합니다)
  • 응용 프로그램 계층 연결 방지 (HTTP / FTP / IMAP 서비스에 연결)
  • Python 또는 다른 언어로 외부 유틸리티를 호출하지 마십시오 (타사 솔루션에 의존하지 않는 언어에 구애받지 않는 솔루션이 필요합니다)

이를 준수하기위한 한 가지 방법은 Google의 퍼블릭 DNS 서버 중 하나에 도달 할 수 있는지 확인하는 것입니다 . 이 서버의 IPv4 주소는 8.8.8.88.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개방적이고 필터링되지 않습니다. 루트가 아닌 사용자 인 경우 Nmap에 대해 sudo또는 -Pn인수 를 사용 하여 제작 된 프로브 패킷을 전송하고 호스트가 작동 중인지 확인하십시오.

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. 이제 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 확인 실패 등으로 인해 속도가 느릴 수 있다고 생각합니다. 그렇지 않으면 의견을 말하십시오.

업데이트 # 1 : @theamk의 의견 덕분에 타임 아웃은 이제 인수이며 3s기본적으로 초기화됩니다 .

업데이트 # 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위 출력에서 ​​각 작성자의 모든 구현이 인터넷 연결을 올바르게 식별 함을 나타냅니다. 시간은 밀리 초 해상도로 표시됩니다.

업데이트 # 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

6
이는 DNS 확인을 피하고 아이러니하게도 포트 53에서 Google의 DNS 서비스에 문의하는 것이 가장 좋은 대답입니다.
m3nda

1
@AviMehenwal Google은 무료로 사용할 수있는 DNS 이름 확인 서비스의 일부로이 IP를 제공합니다. Google이 달리 결정하지 않는 한 IP는 변경되지 않습니다. 몇 년 동안 문제없이 대체 DNS 서버로 사용해 왔습니다.
7h3rAm

1
@Luke 지적 해 주셔서 감사합니다. 예외에 대해 사용자에게 알리고 False를 기본 답변으로 반환하도록 답변을 업데이트했습니다.
7h3rAm

2
@JasonC TCP / 53에 연결하는 것은 포트 53을 통한 DNS 연결과 다릅니다. 유사하게 응용 프로그램에서 사용하는 모든 TCP 포트는 응용 프로그램 수준 프로토콜 연결로 분류됩니다. 아니요, 사실이 아닙니다. TCP 소켓을 통해 포트에 연결하는 것은 응용 프로그램 수준 연결이 아닙니다. 나는 DNS 조회를하지 않고 단지 절반의 TCP 핸드 셰이크를하고 있습니다. 전체 DNS 조회를 수행하는 것과는 다릅니다.
7h3rAm

2
우리 close()는 소켓 을 호출해서는 안 됩니까?
brk

60

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

8
최고 답변은 1 초가 걸리지 만 20 밀리 초 만 걸립니다.
Wally

8
+1 서버가 연결 가능하고 응답하는지 확인하려는 경우 전체 페이지를 다운로드하는 것은 의미가 없습니다. 컨텐츠가 필요한 경우 컨텐츠를 다운로드하십시오
thatsIch

아무 이유없이 URL '8.8'을 사용하는 것은 여전히 ​​작동하지만 분명히 '8.8'또는 ' 8.8 '은 실제 웹 브라우저에서 작동하지 않습니다.
Polv

2 시간 동안 작업 솔루션을 찾은 다음 나는 이것을 발견했습니다 ... 깨끗하고 간단합니다
Pedro Serpa

21

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

보너스 : 이것은 웹 사이트를 핑하는이 기능으로 확장 될 수 있습니다.

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
요청은 훌륭한 도서관입니다. 그러나 여기의 많은 예제와 달리 IANA의 example.com 또는 example.org는 ICANN에 의해 완전히 제어되므로보다 안정적인 장기 선택으로 사용합니다 .
chirale

인터넷 실행 상태를 확인하는 다른 방법이 있습니까? google.com다시 고정 하면 IP가 차단되기 때문입니다. 다른 방법이 있습니까?
Sanjiv

15

파이썬 3.2에서 새로운 코드에 대해 unutbu가 말한 것을 업데이트하기 만하면됩니다.

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

그리고 참고로, 여기에 입력 (참조)은 확인하려는 URL입니다 : 나는 당신이 살고있는 곳에서 빠르게 연결되는 것을 선택하는 것이 좋습니다. 즉, 나는 한국에 살고 있습니다 . /www.naver.com .


사용 가능한 DNS 서버가 없으면 30 초 동안 기다립니다.
Viktor Joras

10

당신은 단지 데이터를 다운로드하려고 시도 할 수 있으며, 연결이 실패하면 연결에 문제가있는 것을 알 수 있습니다.

기본적으로 컴퓨터가 인터넷에 연결되어 있는지 확인할 수 없습니다. 잘못된 DNS 구성, 방화벽, NAT와 같은 여러 가지 실패 이유가있을 수 있습니다. 따라서 일부 테스트를 수행하더라도 시도 할 때까지 API와의 연결을 보장 할 수 없습니다.


2
"허가보다 용서를 구하는 것이 더 쉽다"
cobbal

이럴 필요는 없습니다. 단순히 사이트에 연결하거나 핑을 시도하면 시간 초과가 발생할 수 있습니다. 어떻게해야합니까?
aF.

API에 연결하려고 시도 할 수없는 이유가 있습니까? 실제 연결 전에 확인해야하는 이유는 무엇입니까?
Tomasz Wysocki

파이썬을 사용하여 html 페이지를 만듭니다. html 페이지는 파이썬 프로그램에서 제공하는 인수에 따라 다릅니다. API에 액세스 할 수있는 경우 HTML 코드를 입력하면됩니다. 그래서 내가 전에 알아야 할 이유입니다.
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!' )

파이썬 3의 경우 urllib.request.urlopen(host)


4

어쨌든 시도한 작업을 시도하십시오. 그것이 실패하면 파이썬은 당신에게 알리기 위해 예외를 던져야합니다.

먼저 사소한 조작을 시도하여 연결을 감지하면 경쟁 조건이 발생합니다. 테스트 할 때 인터넷 연결이 유효하지만 실제 작업을 수행하기 전에 다운되면 어떻게됩니까?


3

localhost가 127.0.0.1 Try 에서 변경된 경우 작동하지 않을 수 있습니다

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 주소인지 묻습니다. 희망이 도움이


네트워크에 연결되어 있는지 여부 만 식별하지만 흥미로운 검사입니다. 인터넷이든 NAT의 서브넷이든 여전히 의문의 여지가 있습니다.
7h3rAm

@ 7h3rAm, 좋은 지적이다. DCHP는 인터넷 연결이 필요하지 않다.

IP를받은 네트워크 NIC 연결 만 있으면됩니다. 다른 모든 답변과 달리 LAN, 라우터, 방화벽, ISP에 다른 시스템까지 연결하지 않아도됩니다. DHCP에 할당되지 않은 주소 (정적) 인 경우 NIC가 여전히 연결되어 있음을 보여주지 못함
user150471

@ user150471은 이미 지적 했으므로 귀하의 기여에 감사드립니다.

3

여기 내 버전이 있습니다

import requests

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

1
나는 이것을 좋아하지만 요청에서 발생하는 특정 시간 초과 또는 연결 오류를 제외하면 더 좋습니다. 그대로, 번개처럼 빠른 Ctrl-C는 오프라인으로 인쇄됩니다.
user2561747 2016

2

현대적인 휴대용 솔루션 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

1

가장 좋은 방법은 파이썬이 웹 사이트를 찾을 수없는 경우 항상 제공하는 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("")

1

내가 좋아하는 것, 클러스터에서 스크립트를 실행할 때

import subprocess

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

이것은 아무 것도 다운로드하지 않고 주어진 원격 파일이 웹에 존재하는지 확인하면서 조용히 실행됩니다.


0

unutbu의 대답 을 출발점으로 삼아 과거에 "정적"IP 주소 변경으로 불에 타서 DNS 조회를 사용하여 한 번 확인하는 간단한 클래스를 만들었습니다 (예 : URL " https : // www .google.com ")으로 이동 한 다음 후속 검사에 사용할 응답 서버의 IP 주소를 저장합니다. 이런 식으로 IP 주소는 항상 최신 상태입니다 (수업이 적어도 몇 년마다 한 번씩 다시 초기화되었다고 가정). 또한 이 답변에 대해 gawry에게 신용을 주며 , 서버의 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()

0

식스의 답변을 얻는다 나는 기술적 인 문제로 새로운 이민자들이 길을 잃었 기 때문에 어떻게 든 단순화 할 수 있다고 생각한다.

마지막으로 PV 모니터링을 위해 하루에 한 번 연결 (3G, 느림)이 설정 될 때까지 기다리는 데 사용합니다.

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 분에 도달하면 한 시간 안에 다른 스크립트를 시도합니다!


귀하의 essai var가 사용되지 않습니까?
kidCoder

0

내 라우터가 IP 주소 192.168.0.1을 전달하고 google.com을 쿼리 할 때 인터넷에 연결되어 있지 않으면 헤드를 반환하므로 Ivelin의 답변얻고 추가 검사를 추가하십시오.

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

이것은 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

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

내 프로젝트 에는 Google 공개 DNS 서버 8.8.8.8을 핑하도록 수정 된 스크립트를 사용 합니다. 외부 종속성없이 1 초의 타임 아웃 및 핵심 파이썬 라이브러리 사용 :

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

선택 제한 시간 값은 1이지만, 본 예에서는 1 초 이상 더 쉽게 실패 선택 부동 소수점 숫자 일 수있다.


0

요청을 가져 와서이 간단한 파이썬 코드를 사용해보십시오.

def check_internet():
url = 'http://www.google.com/'
timeout = 5
try:
    _ = requests.get(url, timeout=timeout)
    return True
except requests.ConnectionError:
return False
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.