[英]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
一个超时的线程。 或者,您可以等待后台线程可以发出信号的Condition
或Event
,或者使用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.