我尝试使用以下代码使用python建立HTTP连接。我自己进行DNS解析,因为我无法在相关机器上更改诸如hosts
和resolv.conf
文件之类的内容。
class resolver(object):
def __init__(self, server):
self.server = server
def __call__(self, host):
res = check_output('host %s %s' % (host, self.server), shell = True)
ips = findall('has address (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})', res)
return choice(ips)
class http_connection(httplib.HTTPConnection):
dns_server = '8.8.8.8'
def connect(self):
resolv = resolver(http_connection.dns_server)
self.sock = socket.create_connection((resolv(self.host), self.port), self.timeout)
...
x = http_connection('%s:%d' % (args.host, args.port))
x.request('GET','/start/')
rep = x.getresponse()
print rep.read()
一切正常,我从DNS获取IP,创建了套接字(使用ip端口对,而不是主机名),并且得到了答案。唯一的事情是,这需要很长时间,最多需要5-6秒。调试后,我发现由于某种原因,对解析的IP进行反向DNS查找会超时。我在/etc/hosts中添加了一个条目之后,通过在另一台机器上重现它来验证这是问题所在,一切都以我期望的速度运行。同样,值得这样做:使用curl或wget也会产生RDNS。
我看到了两种方法可以解决此问题,但找不到实际实现它们的方法:
尽可能地,因此有一种方法可以强制此查找
我提供的dns_server(不在resolv.conf中)。
直至setsockopt级别。
最佳答案
我终于找到了解决这个问题的方法。显然,当我自己没有明确提供源地址并让系统选择时,就会发生这种情况。我想象Linux会采取一些技巧来找出最适合使用的接口(interface),而RDNS就是其中之一。
通过提供如下的source_address,一切正常:
class http_connection(httplib.HTTPConnection):
def __init__(self, dns_server, *args, **kwargs):
httplib.HTTPConnection.__init__(self, *args, **kwargs)
self.resolv = resolver(dns_server, self.source_address)
def connect(self):
self.sock = socket.create_connection((self.resolv(self.host), self.port), self.timeout, self.source_address)
...
x = http_connection(args.dns_server, '%s:%d' % (args.host, args.port), source_address = (args.source_address, 0))