【问题标题】:Python check For network connectionPython 检查网络连接
【发布时间】:2020-08-24 19:43:55
【问题描述】:

我想知道是否有任何 python 脚本(更好的命令)可以告诉我我是否连接到网络。

我不是在谈论“INTERNET”,而是在谈论有线或无线“NETWORK” (所以请不要将此问题设置为重复)

我的意思是我的调制解调器路由器已打开并且我已连接到它(它是否有互联网并不重要)所以脚本返回 True (最好不要使用 ping 等终端命令)

还有另一个问题可能是这个问题的答案: 获取requests.get('192.168.1.1').status_code 是否很好,如果它是 200,我们已连接到网络?

【问题讨论】:

  • 你在用什么操作系统
  • @MZ 我想要一个适用于所有操作系统的脚本,但首先是 'linux' 然后是 'windows'
  • 也许你想检查一个 ping 函数 (stackoverflow.com/questions/26468640/…)
  • @MZ 就像我说的我不想 ping (或任何其他终端命令,如果存在)。但是如果我想使用 ping,使用什么 ip 进行测试? 192.168.1.1?
  • 这将为您提供默认网关的地址 - 应该是您的互联网路由器 - stackoverflow.com/a/6556951/13596037。尝试 ping 那个。

标签: python networking


【解决方案1】:

还有另一个问题可能是这个问题的答案:获取 requests.get('192.168.1.1').status_code 是否好,如果它的 200 我们连接到网络?

这不是个好主意。

  • 如果本地网络不是192.168.1.0/24怎么办?
  • 如果网关不是192.168.1.1怎么办?
  • 如果路由器没有 HTTP 接口怎么办?

您可以做的唯一明智的事情是选择一个众所周知的端点(例如“google.com”)并尝试与其联系(例如,requests.get("http://google.com"))。如果它有效......太好了,你已经连接了!如果它不起作用,则说明您没有足够的信息来确定您是否已连接。

如果您只对本地网络连接感兴趣,您可以先确定您的默认网关地址(例如,通过在 Linux 下运行 ip route,或在 Windows 上运行 route print),然后尝试 ping 通该地址。再一次,您只能检测到一个肯定的结果:如果您收到回复,则说明您已连接,但如果您没有收到,则您不知道您是否已连接。

【讨论】:

  • 这里有一个有用的函数,它将获取 Linux 上的默认网关 stackoverflow.com/a/6556951/13596037 。可能还值得一提的是,requests.get() 的参数是一个 URL,只给它一个 IP 地址是无效的。
  • 我说“不是互联网”。我没有互联网,但我已连接到网络。这个答案对我来说还不够,因为我说我想要 python 命令而不是终端。使用route print 我需要获取输出,然后通过正则表达式模式对其进行过滤。因为此输出在其他设备中可能会有所不同,所以我认为它无法正常工作。
  • 我认为您可能错过了满足您“非互联网”要求的答案的第二部分。很抱歉您对使用终端命令感到不舒服;在该领域获得更多经验可能会对您将来有所帮助。
【解决方案2】:

@larsks 所说的一切都是正确的。 另外您可以检查您的主机(或只有本地主机)上是否有 IP 地址。

你可以做什么:

  • 检查你的盒子上是否有一个IP地址,它不同于本地主机,环回地址范围

  • 如果您知道默认网关(您可以获得)您可能会 ping 默认网关 - 但这可能会失败,因为 ICMP ping 数据包可能在该默认网关上被禁用。

为了避免 TOCTOU 错误 - 只需使用地址并捕获错误! (见:https://en.wikipedia.org/wiki/Time-of-check_to_time-of-use

这里是我通常在该上下文中使用的函数:

def get_host_ip_or_localhost() -> Union[str, None]:
    """
    >>> result = get_host_ip_or_localhost()
    >>> assert is_valid_ip_adress(result)
    """
    host_ip = get_host_ip()

    if not host_ip:                                                                     # pragma: no cover
        logger.warning('can not get default gateway IP, setting localhost as IP')       # pragma: no cover
        host_ip = socket.gethostbyname('localhost')                                     # pragma: no cover
    return host_ip


def ip_is_localhost(host_ip: str) -> bool:
    """
    >>> ip_is_localhost('127.0.0.1')
    True
    >>> ip_is_localhost('localhost')
    True
    >>> ip_is_localhost('192.168.168.17')
    False
    >>> ip_is_localhost('192.168.168.254')
    False
    """
    host_ip = socket.gethostbyname(host_ip)
    local_host_ip = socket.gethostbyname('localhost')
    if host_ip == local_host_ip or host_ip.startswith('127.'):
        return True
    else:
        return False


def get_host_ip() -> Union[str, None]:
    """
    >>> result = get_host_ip()
    >>> assert is_valid_ip_adress(result)
    """
    o_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    # noinspection PyBroadException
    try:
        # doesn't even have to be reachable
        o_socket.connect(('1.1.1.1', 1))
        s_ip = str(o_socket.getsockname()[0])  # type: Union[str, None]
    except Exception:           # pragma: no cover
        s_ip = None             # pragma: no cover
    finally:
        o_socket.close()
    return s_ip


def is_internet_connected(ip_adress: str = '1.1.1.1') -> bool:
    """
    >>> is_internet_connected()
    True
    >>> is_internet_connected(ip_adress='www.un-kno-wn.com')
    False
    """
    response = lib_ping.ping(target=ip_adress, times=1)
    return bool(response.reached)


def is_valid_ip_adress(address: str) -> bool:
    """
    check if it is valid IPV4 or IPV6 Adress
    >>> is_valid_ip_adress('1.1.1.1')
    True
    >>> is_valid_ip_adress('::1')
    True
    >>> is_valid_ip_adress('unknown')
    False
    """
    if is_valid_ipv4_address(address) or is_valid_ipv6_address(address):
        return True
    else:
        return False


def is_valid_ipv4_address(address: str) -> bool:
    """
    >>> is_valid_ipv4_address('1.1.1.1')
    True
    >>> is_valid_ipv4_address('1.1.1.')
    False
    >>> is_valid_ipv4_address('unknown')
    False
    """
    try:
        socket.inet_pton(socket.AF_INET, address)
    except AttributeError:                      # pragma: no cover      # no inet_pton here, sorry
        try:                                    # pragma: no cover
            socket.inet_aton(address)           # pragma: no cover
        except socket.error:                    # pragma: no cover
            return False                        # pragma: no cover
        return address.count('.') == 3          # pragma: no cover
    except socket.error:                        # not a valid address
        return False

    return True


def is_valid_ipv6_address(address: str) -> bool:
    """
    >>> is_valid_ipv6_address('::1')
    True
    >>> is_valid_ipv6_address('127.0.0.1')
    False
    >>> is_valid_ipv6_address('unknown')
    False
    """
    try:
        socket.inet_pton(socket.AF_INET6, address)
    except socket.error:  # not a valid address
        return False
    return True

【讨论】:

  • 哦,完全错了。这根本与本地主机无关。 127.0.0.1检查网络连接有什么用?!
  • @RAMIN-RX7,如果你只有一个环回接口,你没有连接到局域网!所以 - 你不能真正确定你是否连接到局域网,如果你不能 ping 默认网关,但你可以检查你是否有一个与环回地址不同的本地 IP 地址。如果您的主机适配器上没有 IP 地址,请确保您没有连接。
猜你喜欢
  • 1970-01-01
  • 2012-04-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-05
  • 2019-10-03
  • 1970-01-01
相关资源
最近更新 更多