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

时间:2013-07-02 19:22:49

标签: python multithreading sockets

我找到了一个讨论here的选项,如果主机连接到网络,该选项很有效。但是,如果主机未连接,socket.gethostbyname(hostname)会挂起很长时间。

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

我发现这个讨论How to find running time of a thread in 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()

2 个答案:

答案 0 :(得分:2)

这里实际上不需要对gethostbyname进行阻止调用。

首先,你可能根本不想进行DNS查找,而且几乎所有你可以用套接字做的事情 - 例如,connect - 已经处理了超时。

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

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

那么,你是怎么做到的?

好吧,你可以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

答案 1 :(得分:1)

如果你在Windows系统上 你可以用这个

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