我正在尝试理解 TCP/IP 堆栈中的应用层协议。我知道 HTTP 和 DNS 协议都位于顶层(应用层)。因此,当浏览器想要访问资源时,它必须向 HTTP 服务器发送请求,例如:
GET www.pippo.it/hello.htm HTTP/1.1
按照HTTP协议规则发出此请求,它使用页面URL,而不是IP地址。
我知道 DNS 请求对于将 URL 转换为 IP 是必需的。所以我的问题是:HTTP 会调用 DNS 协议吗?在我看来这是不可能的,因为两者都是顶层协议(因此 DNS 无法为 HTTP 提供服务)。同样,即使是 TCP(处于较低级别)也无法向 DNS 等更高级别的协议请求服务。
那么 DNS 请求何时发生?谁执行这样的请求?
答案1
有问题的 HTTP 请求实际上是除非浏览器正在与中介(代理)对话,否则无效。
如果浏览器直接与 Web 服务器通信,则示例将更类似于以下内容:
GET /hello.htm HTTP/1.1
Host: www.pippo.it
现在,为了更好地理解这一点,我们来考虑一下 OSI 模型:
我们正在运行 3 个系统:
- A客户运行浏览器
- A网络服务器为网站提供服务
- ADNS 服务器了解网站的 IP 地址
所涉及的协议从下到上(与 OP 相关的最小集)如下:
- 知识产权
- TCP、UDP
- HTTP、DNS
HTTP 通信通过 TCP 协议完成(TCP 位于 IP 协议之上),而在这种情况下,DNS 通信通过 UDP 协议完成(UDP 也位于 IP 协议之上)。
简短的沟通顺序如下:
这客户运行浏览器,询问DNS 服务器获取
A
的记录www.pippo.it
,使用 UDP 协议。1.1. 在客户端,操作系统负责解析部分并与浏览器对话 --- 浏览器从不直接与 DNS 服务器对话,而是通过操作系统调用获取主机名()或较新的获取地址信息()在 Windows 上,操作系统解析地址的顺序可能由类似以下内容定义:这而在 Linux 上,解析优先级定义为
/etc/nsswitch.conf
这DNS 服务器使用 UDP 协议,响应客户如果存在,则包含记录/IP 地址
这客户在端口 80 上打开 TCP 连接网络服务器并写下以下文字:
HTTP 请求:
GET /hello.htm HTTP/1.1
Host: www.pippo.it
您可以通过在控制台或命令提示符中执行类似这样的操作来模仿同样的事情:
> telnet www.pippo.it 80
Trying 195.128.235.49...
Connected to www.pippo.it.
Escape character is '^]'.
GET /hello.htm HTTP/1.1
Host: www.pippo.it
后面跟着两行空行。如果请求的内容存在,Web 服务器会将其打印在屏幕上。如果另一端有浏览器,响应文本会被浏览器解析,所有标签、链接、脚本和图像都会呈现在我们所谓的网页中。
实际上,还有一些细节,例如,如果您已经访问过某个域,浏览器可能会缓存 IP 地址,这样 DNS 解析就变得没有必要了。此外,现代浏览器可能会在您实际需要之前尝试进行解析(DNS 预取)来加快您的浏览速度。
此外,您的计算机可能在hosts
文件中有静态记录。如果记录与请求匹配,则首先使用本地静态条目,并且不会联系任何 DNS 服务器。这是可配置的,不一定是真的,但它是我熟悉的操作系统上的默认设置。
答案2
HTTP 通过 TCP 传输,TCP 是一种 IP 协议。要发出 HTTP 请求,浏览器必须打开 TCP 连接,为此,它需要目标 IP 地址(即服务器的 IP 地址)。要解决服务器的主机名,因此它必须发出 DNS 请求(通常,DNS 请求本身是由操作系统在程序调用其名称解析功能时发送的;但是,没有什么可以阻止程序自己向 DNS 服务器发送 DNS 请求)。一旦建立连接,它就可以发送 HTTP 请求,其中包含所请求资源的路径,以及主持人字段中填写服务器的主机名(例如Host: www.pippo.it
)。主机名不不是进入请求行(实际上是GET /hello.htm HTTP/1.1
),除非请求被发送到 HTTP 代理(在这种情况下,完整的 URL 是存在的,包括协议部分,例如GET http://www.pippo.it/hello.htm HTTP/1.1
),
答案3
流程如下:
- 用户(你)给浏览器一个 URL,例如
http://www.pippo.it/hello.htm
浏览器将其分为三个部分:
- 协议
http
- 主机名
www.pippo.it
- URL 路径
/hello.htm
(更复杂的 URL 也可能有其他部分,我现在将忽略这种可能性)
- 协议
浏览器知道,要创建 IP 连接,它需要一个 IP 地址。要获取 IP 地址,它需要使用 DNS(除非它缓存了该地址)。
- 浏览器向操作系统询问 DNS 服务器的 IP 地址;假设它得到的是
8.8.8.8
。 浏览器构建了如下的多层连接:
- IP层:连接到
8.8.8.8
- UDP 层:设置数据包的目标端口为 53
A
DNS 层:为主机名记录创建 DNS 请求www.pippo.it
当然,我省略了很多细节,例如涉及的数据包的确切格式。
- IP层:连接到
- 浏览器收到 DNS 响应(位于 UDP 之上,位于 IP 之上等),该响应提供了 IP 地址
www.pippo.it
,假设它是10.11.12.13
- 浏览器向操作系统询问 DNS 服务器的 IP 地址;假设它得到的是
- 浏览器知道,要创建 TCP 连接,它需要一个端口号。为了获取端口号,它会
http
在其内部表中查找协议,并了解到应该使用端口 80。 浏览器构建了如下的多层连接:
- IP层:连接到
10.11.12.13
- TCP 层:将数据包设置到目标端口 80
/hello.htm
HTTP 层:为主机上的URL 创建 HTTP 请求www.pippo.it
(因为计算机10.11.12.13
可能托管多个域,因此需要知道所需的域)GET /hello.htm HTTP/1.1 Host: www.pippo.it ...
当然,我省略了 TCP 握手等所有细节。
- IP层:连接到
- 浏览器收到 HTTP 响应(位于 TCP 之上,位于 IP 之上等),其中包含以下内容
hello.htm
为了保险起见,我要说的是,浏览器现在会检查该响应的内容,并识别所需的任何其他资源:图像、CSS、Javascript 等。然后,它会对每个这样的资源重复整个过程。