《Python网络编程基础》第四章 域名系统
2015-09-27 21:05
519 查看
域名系统(DNS) 是一个分布式的数据库,它主要用来把主机名转换成IP地址。DNS以及相关系统之所以存在,主要有以下两个原因:
它们可以使人们比较容易地记住名字,如www.baidu.com。
它们允许服务器改变IP地址,但是还用同样的名字。
作为一个例子,让我们看一下查询 www.baidu.com 首先,您的程序会和操作系统配置文件指定的本地名称服务器通信。这个服务器是一个递归的名称服务器,它收到请求并以适当的方式传递下去,它会为您完成大量工作。
递归服务器做的第一件事情是询问.com域。后者有个内置的顶级域名列表,这些服务器可以分发世界上顶级域名的信息,例如.com
![](http://images2015.cnblogs.com/blog/629459/201509/629459-20150927205123178-1123911634.png)
这个循环重复多次,直到最终查询到达www.baidu.com服务的名称服务器。这个服务器知道问题中的IP地址,并返回它。
使用操作系统查询服务
操作系统本身带一些用于DNS查找的功能(经常被称为resolver库)。
![](http://images2015.cnblogs.com/blog/629459/201509/629459-20150927205220069-751431333.png)
执行基本查询
最基本的查询是正向查询,它根据一个主机名来查找IP地址。例如你想从www.baidu.com上下载一个Web页面。首先您需要找到IP地址。
在Python中,您将用到的函数是socket.getaddrinfo(),
![](http://images2015.cnblogs.com/blog/629459/201509/629459-20150927205659944-1091175285.png)
sockaddr实际上就是远程机器的地址。
![](http://images2015.cnblogs.com/blog/629459/201509/629459-20150927205732569-2065605731.png)
这里的值是以tuple的形式打印出来的。
![](http://images2015.cnblogs.com/blog/629459/201509/629459-20150927205806944-1023623086.png)
通过getaddrinfo()获得全部的条目也是可以的。
import sys,socket
result = socket.getaddrinfo(sys.argv[1],None)
counter = 0
for item in result:
print "%-2d: %s" % (counter,item[4])
counter += 1
注意:同一条目在您的机器上也许不会显示多次。在某些平台上,例如Windows的getaddrinfo()默认只支持一种协议。即使在支持多协议的平台上,如果有些协议没有配置,也会只有一个结果。为了限制结果,让每个条目只显示一次,您需要为protocol参数设定socket.SOCK_STREAM为family参数设定0,让它支持所有family
这里有一个上个例子的更好的版本:
import sys,socket
result = socket.getaddrinfo(sys.argv[1],None,0,socket.SOCK_STREAM)
counter = 0
for item in result:
print "%-2d: %s" % (counter,item[4])
counter += 1
这一次,您将看到每一个条目只显示一次。
执行反向查询
![](http://images2015.cnblogs.com/blog/629459/201509/629459-20150927210101350-1975813465.png)
反向查找基础
有一个重要的问题需要您明白,那就是,对于一个IP地址,完全有可能不存在反向的映射。事实上,很多IP地址根本就没有对应的域名。所以,您需要确保为每一个反向查找的行为捕获和处理socket.herror()。
import sys,socket
try:
# Perform the lookup
result = socket.gethostbyaddr(sys.argv[1])
print "Primary hostname:"
print " " + result[0]
print "\nAddresses:"
for item in result[2]:
print " " + item
except socket.herror, e:
print "Couldn't look up name:", e
![](http://images2015.cnblogs.com/blog/629459/201509/629459-20150927210136397-995413806.png)
对于反向查询,授权是基于IP地址的。
![](http://images2015.cnblogs.com/blog/629459/201509/629459-20150927210207522-1073143695.png)
import sys,socket
def getipaddrs(hostname):
result = socket.getaddrinfo(hostname,None,0,socket.SOCK_STREAM)
return [x[4][0] for x in result]
def gethostname(ipaddr):
return socket.gethostbyaddr(ipaddr)[0]
try:
hostname = gethostname(sys.argv[1])
ipaddrs = getipaddrs(hostname)
except socket.herror,e:
print "No host names available for %s;this may be normal." % sys.argv[1]
sys.exit(0)
except socket.gaierror,e:
print "Got hostname %s,but it could not be forward-resolved: %s" % (hostname,str(e))
sys.exit(1)
if not sys.argv[1] in ipaddrs:
print "Got hostname %s. but on forward lookup," % hostname
print "original IP %s did not appear in IP address list." % sys.argv[1]
#print "\n %s" % (hostname)
sys.exit(1)
print "Validated hostname:%s" % (hostname)
获得环境信息
import sys,socket
def getipaddrs(hostname):
result = socket.getaddrinfo(hostname,None,0,socket.SOCK_STREAM)
return [x[4][0] for x in result]
hostname = socket.gethostname()
print "Host name:", hostname
print "Fully-qualified name:", socket.getfqdn(hostname)
try:
print "IP address:",getipaddrs(hostname)
except socket.gaierror,e:
print "Couldn't not get IP addresses: %s",(e)
使用PyDNS进行高级查询
DNS Records
当您执行任何类型的查询时,不管是通过PyDNS,还是通过前面介绍的操作系统的查询功能,您都会得到来自一个域名服务器多种类型的records。下面是您会遇到的大多数records列表:
![](http://images2015.cnblogs.com/blog/629459/201509/629459-20150927210316990-1769346945.png)
简单的PyDNS查询
PyDNS 库提供了 Python模块DNS。首先您应该在应用程序中调用DNS.DiscoverNameServers() 它可以使您找到系统中的名称服务器,在Windows系统中是注册表(registry),在UNIX系统上是 /etc/resolv.conf 全部的Pydns查询会被发送到这些服务器上。
![](http://images2015.cnblogs.com/blog/629459/201509/629459-20150927210350037-1243647138.png)
初始化名称服务器后,下一步需要建立一个请求对象,这是通过调用DNS.Request()来实现的。这个对象可以用来发出任何DNS查询请求。
import sys,DNS
query = sys,DNS
query = sys.argv[1]
DNS.DiscoverNameServers()
reqobj = DNS.Request()
answerobj = reqobj.req(name = query,qtype = DNS.Type.ANY)
if not len(answerobj.answers):
print "NOT FOUND."
for item in answerobj.answers:
print "%-5s %s" % (item['typename'],item['data'])
没用啊!!!!
查询特殊的名称服务器
它们可以使人们比较容易地记住名字,如www.baidu.com。
它们允许服务器改变IP地址,但是还用同样的名字。
作为一个例子,让我们看一下查询 www.baidu.com 首先,您的程序会和操作系统配置文件指定的本地名称服务器通信。这个服务器是一个递归的名称服务器,它收到请求并以适当的方式传递下去,它会为您完成大量工作。
递归服务器做的第一件事情是询问.com域。后者有个内置的顶级域名列表,这些服务器可以分发世界上顶级域名的信息,例如.com
![](http://images2015.cnblogs.com/blog/629459/201509/629459-20150927205123178-1123911634.png)
这个循环重复多次,直到最终查询到达www.baidu.com服务的名称服务器。这个服务器知道问题中的IP地址,并返回它。
使用操作系统查询服务
操作系统本身带一些用于DNS查找的功能(经常被称为resolver库)。
![](http://images2015.cnblogs.com/blog/629459/201509/629459-20150927205220069-751431333.png)
执行基本查询
最基本的查询是正向查询,它根据一个主机名来查找IP地址。例如你想从www.baidu.com上下载一个Web页面。首先您需要找到IP地址。
在Python中,您将用到的函数是socket.getaddrinfo(),
![](http://images2015.cnblogs.com/blog/629459/201509/629459-20150927205659944-1091175285.png)
sockaddr实际上就是远程机器的地址。
![](http://images2015.cnblogs.com/blog/629459/201509/629459-20150927205732569-2065605731.png)
这里的值是以tuple的形式打印出来的。
![](http://images2015.cnblogs.com/blog/629459/201509/629459-20150927205806944-1023623086.png)
通过getaddrinfo()获得全部的条目也是可以的。
import sys,socket
result = socket.getaddrinfo(sys.argv[1],None)
counter = 0
for item in result:
print "%-2d: %s" % (counter,item[4])
counter += 1
注意:同一条目在您的机器上也许不会显示多次。在某些平台上,例如Windows的getaddrinfo()默认只支持一种协议。即使在支持多协议的平台上,如果有些协议没有配置,也会只有一个结果。为了限制结果,让每个条目只显示一次,您需要为protocol参数设定socket.SOCK_STREAM为family参数设定0,让它支持所有family
这里有一个上个例子的更好的版本:
import sys,socket
result = socket.getaddrinfo(sys.argv[1],None,0,socket.SOCK_STREAM)
counter = 0
for item in result:
print "%-2d: %s" % (counter,item[4])
counter += 1
这一次,您将看到每一个条目只显示一次。
执行反向查询
![](http://images2015.cnblogs.com/blog/629459/201509/629459-20150927210101350-1975813465.png)
反向查找基础
有一个重要的问题需要您明白,那就是,对于一个IP地址,完全有可能不存在反向的映射。事实上,很多IP地址根本就没有对应的域名。所以,您需要确保为每一个反向查找的行为捕获和处理socket.herror()。
import sys,socket
try:
# Perform the lookup
result = socket.gethostbyaddr(sys.argv[1])
print "Primary hostname:"
print " " + result[0]
print "\nAddresses:"
for item in result[2]:
print " " + item
except socket.herror, e:
print "Couldn't look up name:", e
![](http://images2015.cnblogs.com/blog/629459/201509/629459-20150927210136397-995413806.png)
对于反向查询,授权是基于IP地址的。
![](http://images2015.cnblogs.com/blog/629459/201509/629459-20150927210207522-1073143695.png)
import sys,socket
def getipaddrs(hostname):
result = socket.getaddrinfo(hostname,None,0,socket.SOCK_STREAM)
return [x[4][0] for x in result]
def gethostname(ipaddr):
return socket.gethostbyaddr(ipaddr)[0]
try:
hostname = gethostname(sys.argv[1])
ipaddrs = getipaddrs(hostname)
except socket.herror,e:
print "No host names available for %s;this may be normal." % sys.argv[1]
sys.exit(0)
except socket.gaierror,e:
print "Got hostname %s,but it could not be forward-resolved: %s" % (hostname,str(e))
sys.exit(1)
if not sys.argv[1] in ipaddrs:
print "Got hostname %s. but on forward lookup," % hostname
print "original IP %s did not appear in IP address list." % sys.argv[1]
#print "\n %s" % (hostname)
sys.exit(1)
print "Validated hostname:%s" % (hostname)
获得环境信息
import sys,socket
def getipaddrs(hostname):
result = socket.getaddrinfo(hostname,None,0,socket.SOCK_STREAM)
return [x[4][0] for x in result]
hostname = socket.gethostname()
print "Host name:", hostname
print "Fully-qualified name:", socket.getfqdn(hostname)
try:
print "IP address:",getipaddrs(hostname)
except socket.gaierror,e:
print "Couldn't not get IP addresses: %s",(e)
使用PyDNS进行高级查询
DNS Records
当您执行任何类型的查询时,不管是通过PyDNS,还是通过前面介绍的操作系统的查询功能,您都会得到来自一个域名服务器多种类型的records。下面是您会遇到的大多数records列表:
![](http://images2015.cnblogs.com/blog/629459/201509/629459-20150927210316990-1769346945.png)
简单的PyDNS查询
PyDNS 库提供了 Python模块DNS。首先您应该在应用程序中调用DNS.DiscoverNameServers() 它可以使您找到系统中的名称服务器,在Windows系统中是注册表(registry),在UNIX系统上是 /etc/resolv.conf 全部的Pydns查询会被发送到这些服务器上。
![](http://images2015.cnblogs.com/blog/629459/201509/629459-20150927210350037-1243647138.png)
初始化名称服务器后,下一步需要建立一个请求对象,这是通过调用DNS.Request()来实现的。这个对象可以用来发出任何DNS查询请求。
import sys,DNS
query = sys,DNS
query = sys.argv[1]
DNS.DiscoverNameServers()
reqobj = DNS.Request()
answerobj = reqobj.req(name = query,qtype = DNS.Type.ANY)
if not len(answerobj.answers):
print "NOT FOUND."
for item in answerobj.answers:
print "%-5s %s" % (item['typename'],item['data'])
没用啊!!!!
查询特殊的名称服务器
![](http://images2015.cnblogs.com/blog/629459/201509/629459-20150927210422787-1081012987.png)
相关文章推荐
- 网络知识小笔记
- HDU 5493 Queue (合肥网络赛 1010 )
- HDU 5489 Removed Interval (合肥网络赛 1006 )
- No mapping found for HTTP request with URI [/...] in DispatcherServlet with name ...的解决方法
- sendmsg和recvmsg
- HDU 5491 The Next (二进制) 2015合肥网络赛
- Android之Http沟通——4.Android HTTP索取信息:HttpClient
- 【2015/9/27】Linux学习日志_Day2 终端命令 一些网络命令
- 黑马程序员——网络编程
- HDU 5478 Can you find it 2015ICPC上海网络赛
- HDU 5492 Find a path (dp) 2015合肥网络赛
- 大型网站的 HTTPS 实践(1):HTTPS 协议和原理
- Linux网络编程---I/O多路复用 之 select
- HDU 5475 An easy problem 2015ICPC 上海网络赛
- 传智播客c/c++公开课学习笔记--Linux网络流媒体服务器的核心代码揭秘
- TCP基础
- HTTPD 工作原理
- Xcode7 使用NSURLSession发送HTTP请求报错
- OpenStack OVS GRE/VXLAN网络
- Http服务器实现文件上传与下载(二)