繁体   English   中英

python检查主机是否连接到网络

[英]python check to see if host is connected to network

我发现这里讨论的一个选项,如果主机连接到网络,它可以很好地工作。 但是,如果未连接主机,则socket.gethostbyname(hostname)挂起很长时间。

我看到了一个在线程中运行socket.gethostbyname(hostname)的建议,如果这个线程没有在指定的时间内返回结果,则认为它没有连接。 我认为这是一个好主意,但我对线程(虽然我已经成功使用它)知道如何做到这一点还不够熟练。

我发现这个讨论如何在Python中找到一个线程的运行时间似乎暗示这不是微不足道的。 有任何想法吗? 谢谢。

编辑:

我必须承认自己的无知。 我没有意识到(虽然我应该) socket.gethostbyname(hostname)正在进行DNS查找。 所以,我把这个简单的方法放在一起测试端口22上感兴趣的主机的套接字连接:

#! /usr/bin/python

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(0.5)

try:
        s.connect(('192.168.2.5',22)) 
except Exception, e:
        print 'connection failed'

s.close() 

注意:这不会检查与网络的现有连接,如果未连接则会挂起。

此脚本将首先检查与网络的连接,如果找到连接,则它将检查该网络上的特定主机:

#! /usr/bin/python

import socket
import fcntl
import struct

def check_connection():

        ifaces = ['eth0','wlan0']
        connected = []

        i = 0
        for ifname in ifaces:

            s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            try:
                socket.inet_ntoa(fcntl.ioctl(
                        s.fileno(),
                        0x8915,  # SIOCGIFADDR
                        struct.pack('256s', ifname[:15])
                )[20:24])
                connected.append(ifname)
                print "%s is connected" % ifname
            except:
                print "%s is not connected" % ifname

            i += 1

        return connected

connected_ifaces = check_connection()

if len(connected_ifaces) == 0:
    print 'not connected to any network'
else:
    print 'connected to a network using the following interface(s):'
    for x in connected_ifaces:
        print '\t%s' % x

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.settimeout(0.5)

    try:
            s.connect(('192.168.2.5',22)) 
            print 'connected to hostname'
    except Exception, e:
            print 'connection to hostname failed'

    s.close()

很有可能在这里实际上不需要对gethostbyname进行阻塞调用。

首先,您可能根本不想进行DNS查找,而且几乎所有其他操作都可以使用套接字 - 例如, connect -already处理超时。

其次,如果你确实需要在DNS查找上超时,你可能想要使用像pycares这样的异步DNS库。

但是如果你需要在DNS查找上超时,并且你不能依赖外部代码,那么你是对的,你将不得不在另一个线程中运行DNS查找,并在主线程中等待它。

那么,你是怎么做到的?

好吧,你可以join一个超时的线程。 或者,您可以等待后台线程可以发出信号的ConditionEvent ,或者使用select ,在后台线程可以写入的pipe上等待。

最简单的事情可能是join超时...除非您最终在超时后离开后台线程,如果您在完成之前尝试退出,Python可能(并且将在大多数主要平台上使用CPython 2.7或3.3)在退出之前等待它结束。 解决这个问题的方法是使用daemon线程,但是你不能合法地join它。 您可以在超时后对其进行守护,但我认为Event更简单。

所以,例如:

event = threading.Event()

def blocking_dns():
    socket.gethostbyname(host)
    event.set()

thread = threading.Thread(target=blocking_dns)
thread.daemon = True
thread.start()
success = event.wait(timeout)

这是一个通用的包装器:

def run_with_timeout(timeout, func, *args, **kwargs):
    event = threading.Event()
    def wrapper():
        func(*args, **kwargs)
        event.set()
    thread = threading.Thread(target=wrapper, args=args, kwargs=kwargs)
    thread.daemon = True
    thread.start()
    return event.wait(timeout)

您可以这样使用:

dns_works = run_with_timeout(5.0, socket.gethostbyname, 'www.google.com')

使用Event来处理比这更简单的事情变得棘手(并且通常你不会发现它很棘手,并且编写代码可以在99%的时间内工作并且无法调试其他1%)。 通常的问题是你可以从后台线程中错过该set 如果你在检查之前不关心这个set ,或者只是在你开始等待之后,你可以使用Event ; 否则,你需要Condition

如果你在Windows系统上,你可以使用它

x = os.system("ping -n 1  google.com")
if x == 0: 
    print "HOST IS CONNECTED  :) "

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM