python检查主机是否连接到网络 [英] python check to see if host is connected to network

查看:1311
本文介绍了python检查主机是否连接到网络的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发现在此处中讨论了一个选项,如果主机已连接到网络.但是,如果未连接主机,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)已经可以处理超时.

第二,如果您确实确实需要DNS查找超时,则可能要使用异步DNS库,例如 pycares .

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

那么,你怎么做到的?

好吧,您可以 join a线程超时.或者,您可以等待 Condition Event 表示后台线程可以发出信号,或者通过select 后台线程可以写入的.python.org/2/library/os.html#os.pipe"rel =" nofollow> 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;否则,可以使用Event.否则,您需要Condition.

I found an option discussed here which works great if the host is connected to the network. However, socket.gethostbyname(hostname) hangs for a long time if the host is not connected.

I saw a suggestion to run socket.gethostbyname(hostname) in a thread and if this thread did not return a result within a specified period, assume it is not connected. This I thought was a good idea, but I am not proficient enough yet with threads (although I have used them successfully) to know how to do this.

I found this discussion How to find running time of a thread in Python which seems to imply that this is not trivial. Any ideas? Thanks.

Edit:

I must admit my own ignorance. I didn't realize (though I should have) that socket.gethostbyname(hostname) was doing a DNS lookup. So, I put together this simple to test for a socket connection to the host of interest on port 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() 

Note: this will not check for an existing connection to a network and will hang if not connected.

This script will check for a connection to a network first, if a connection is found then it will check for a specific host on that network:

#! /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()

解决方案

There's a good chance that the blocking call to gethostbyname isn't actually necessary here.

First, you may not want to do a DNS lookup at all, and almost everything else you can do with sockets—e.g., connect—already handles timeouts.

Second, if you really do need timeouts on DNS lookup, you probably want to use an async DNS library like pycares.

But if you need timeouts on DNS lookups, and you can't rely on external code, then you're right, you will have to run the DNS lookup in another thread, and wait on it in the main thread.

So, how do you do that?

Well, you can join a thread with a timeout. Or you can wait on a Condition or Event that the background thread can signal, or, with select, on a pipe that the background thread can write to.

The simplest thing is probably join with a timeout… except that you end up leaving the background thread running after a timeout, and if you try to quit before it finishes, Python may (and will, with CPython 2.7 or 3.3 on most major platforms) wait around for it to end before quitting. The way to fix that is to use a daemon thread, but then you can't legally join it. You can daemonize it after the timeout, but I think here an Event is simpler.

So, for example:

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)

Here's a general-purpose wrapper:

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)

Which you can use like this:

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

Using an Event for anything less trivial than this gets tricky (and often you can't see that it's tricky, and write code that works 99% of the time and is impossible to debug the other 1%). The usual problem is that you can miss the set from the background thread. If you don't care whether the set happens before you even checked, or only after you've started waiting, you can use Event; otherwise, you need Condition.

这篇关于python检查主机是否连接到网络的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆