2014-10-05 41 views
2

寻找一种方法来解决给定的完全限定的域名的IPv4/IPv6地址,然而在有限的时间内。非阻塞主机名解析?

我试图用一个标准的Ruby库几种方法,但所有的人都阻挡其他线程,以便超时异常不能生效:

Timeout.timeout(1) {addr = Socket.sockaddr_in 80,'google.com'} 
Timeout.timeout(1) {addr = Socket.getaddrinfo 'google.com','http',nil,:STREAM} 
Timeout.timeout(1) {addr = Socket.gethostbyname 'google.com'} 

当DNS响应缓慢或无法访问的瞬间,所有的以上尝试不会在约60秒内停止,而不是1秒。

我知道adns但它不是通常可用的,并且需要安装额外的软件包。

还有其他解决方案吗?

回答

2

最简单的方法是将域查询放在一个线程/进程中,然后定期检查我们是否从中获取了信息。

编辑: 至于如何做到这一点,这里是Python的一个简单的例子:

from multiprocessing import Pool 
import socket 
import time 

def lookup(host): 
    return socket.gethostbyname(host) 

if __name__ == "__main__": 
    pool = Pool(processes=4) 
    result = pool.apply_async(lookup, ("google.com",)) 
    done = 0 
    while done < 60: # Here we do something weird while domain lookups work in background 
     print(done) 
     done += 1 
     time.sleep(1) 

    # Now we need the domain details so we get em 
    print(result.get(1)) # 1 second timeout since it already had 60 seconds to process 

吉尔无关用它作为查找功能将在单独的进程中执行,拥有自己的执行叠加。您可以在excellent python manpages上阅读关于多处理选项的更多信息。

+0

恐怕不行了,因为上面的函数直到完成才阻塞其他线程,所以不可能定期检查它的状态。试用CRuby和CPython的'socket.gethostbyname'。这是由于GIL在外部C库调用期间阻止多个线程。 – 2014-10-05 21:04:40

+0

@DavidUnric我已经用一些细节和多处理示例更新了答案,如何实现你正在尝试做的事情。 – 2014-10-05 21:22:35

+0

谢谢。你的例子确实有效,但是不是一个新线程,而是一个新的独立进程。这是必需的,或者它会在线程中工作吗?我很抱歉,我的主要语言是Ruby,不确定如何在Python中正确测试。 – 2014-10-05 21:35:30