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

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.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值