HTTP GET 方法如何与 DNS 协议相关联?

Gia*_*rlo 19 domain-name-system tcpip http

我正在尝试了解 TCP/IP 堆栈中的应用层协议。我知道 HTTP 和 DNS 协议都停留在顶层(应用层)。因此,当浏览器想要访问资源时,它必须向 HTTP 服务器发送请求,例如:

GET www.pippo.it/hello.htm HTTP/1.1
Run Code Online (Sandbox Code Playgroud)

这个请求遵循 HTTP 协议的规则,它使用页面 URL,而不是 IP 地址。

我知道将 URL 转换为 IP 需要 DNS 请求。所以我的问题是:HTTP 会调用 DNS 协议吗?这对我来说似乎是不可能的,因为两者都是顶层协议(因此 DNS 无法为 HTTP 提供服务)。以同样的方式,即使 TCP(停留在较低级别)也无法在更高级别的协议(如 DNS)上请求服务。

那么DNS请求什么时候发生呢?谁执行了这样的请求?

Hrv*_*jar 40

有问题的 HTTP 请求实际上是无效的,除非浏览器正在与中介(代理)交谈。

如果浏览器直接与 Web 服务器通信,您的示例看起来更像以下内容:

GET /hello.htm HTTP/1.1
Host: www.pippo.it
Run Code Online (Sandbox Code Playgroud)

现在,为了正确看待这一点,请考虑 OSI 模型:

OSI 模型

我们有 3 个系统在运行:

  • 运行浏览器的客户端
  • 一个Web服务器服务的网站
  • 一个DNS服务器知道该网站的IP地址

所涉及的协议是,从下到上(最小相关设置为 OP):

  • 知识产权
  • TCP、UDP
  • HTTP、DNS

HTTP 通信通过 TCP 协议完成(TCP 位于 IP 协议之上),而 DNS 通信在这种情况下通过 UDP 协议完成(UDP 也位于 IP 协议之上)。

简而言之,通信顺序如下:

  1. 运行浏览器的客户端使用 UDP 协议向DNS 服务器请求A记录www.pippo.it

    1.1. 在客户端,由操作系统完成解析部分并与浏览器对话——浏览器从不直接与 DNS 服务器对话,而是通过操作系统调用gethostbyname()或较新的getaddrinfo()。在Windows上,其中OS解析地址的顺序由像很可能定义这个,而在Linux上解决优先级被定义/etc/nsswitch.conf

  2. DNS服务器,使用UDP协议,来响应客户端用一记/ IP地址(如果存在)

  3. 客户端打开的端口80上的TCP连接的Web服务器,并写入以下内容:

    HTTP请求:

    GET /hello.htm HTTP/1.1
    Host: www.pippo.it
    
    Run Code Online (Sandbox Code Playgroud)

    您可以通过在控制台或命令提示符中执行以下操作来模拟相同的事情:

    > 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
    
    Run Code Online (Sandbox Code Playgroud)

    后跟两个空行。如果请求的内容存在,Web 服务器会将其打印在屏幕上。如果另一端有浏览器,则浏览器会解析响应文本,并且所有标签、链接、脚本和图像都在我们所谓的网页中呈现。

实际上还有更多的细节,例如,如果您已经访问过某个域,浏览器可能会缓存 IP 地址,这样 DNS 解析就变得不必要了。此外,现代浏览器可能会尝试在您实际需要之前进行解析(DNS 预取)以加快浏览速度。

此外,您的计算机可能在hosts文件中有静态记录。如果记录与请求匹配,则首先使用本地静态条目,并且不会联系任何 DNS 服务器。这是可配置的,不一定是真的,但它是我熟悉的操作系统的默认设置。

  • @trikly:这就是“主机”标头的用途。没有它,每个 IP 地址只能有一个网站。这是 HTTP/1.0 和 HTTP/1.1 之间的主要区别。谢天谢地,HTTP/1.0 浏览器现在很少见了——但是如果你想迎合它们,那么你需要为每个站点使用不同的 IP 地址(它们仍然可以托管在同一台服务器上)。 (4认同)

Ale*_*Ale 14

HTTP 通过 TCP 传输,TCP 是一种 IP 协议。要发出 HTTP 请求,浏览器必须打开 TCP 连接,为此,它需要目标 IP 地址(即服务器的 IP 地址)。为了解析服务器的主机名,它必须发出一个 DNS 请求(通常当程序调用其名称解析函数时,DNS 请求本身是由操作系统发送的;但是,没有什么可以阻止程序自己向 DNS 发送 DNS 请求服务器)。建立连接后,它可以发送其 HTTP 请求,其中包含所请求资源的路径,以及带有服务器主机名的Host字段(例如,Host: www.pippo.it)。主机名不在请求行上(实际上是GET /hello.htm HTTP/1.1),除非请求被发送到 HTTP 代理(在这种情况下,完整的 URL 存在,包括协议部分,例如GET http://www.pippo.it/hello.htm HTTP/1.1),

  • 实际上,需要 IP 来打开 TCP 连接,在其中传输 HTTP 请求。实际上,客户端和服务器的 IP 地址与连接的所有数据包一起发送。了解它是如何工作的最好方法可能是安装一个数据包捕获工具(Wireshark 是一个优秀的多平台和开源工具),捕获一个简单的 HTTP 请求,从其余的网络活动中过滤掉它,然后看看如何所有的数据包都是通过网络发送的。您实际上也应该能够在 TCP 连接之前看到 DNS 请求。 (6认同)

Dav*_*d Z 8

程序是这样的:

  1. 用户(你)给浏览器一个 URL,比如 http://www.pippo.it/hello.htm
  2. 浏览器将其分为三个部分:

    • 协议 http
    • 主机名 www.pippo.it
    • 网址路径 /hello.htm

    (更复杂的 URL 也可能有其他部分,我暂时忽略这种可能性)

  3. 浏览器知道为了创建 IP 连接,它需要一个 IP 地址。要获得 IP 地址,它需要使用 DNS(除非它缓存了地址)。

    1. 浏览器向操作系统询问 DNS 服务器的 IP 地址;假设它得到8.8.8.8.
    2. 浏览器构建如下多层连接:

      • IP层:连接到 8.8.8.8
      • UDP 层:为目的端口 53 设置数据包
      • DNS 层:A为主机名的记录创建 DNS 请求www.pippo.it

      当然,我省略了很多细节,例如所涉及的数据包的确切格式。

    3. 浏览器收到一个 DNS 响应(分层在 UDP 之上,分层在 IP 之上等),它给出了 的 IP 地址www.pippo.it,假设它是10.11.12.13
  4. 浏览器知道为了创建 TCP 连接,它需要一个端口号。为了获得端口号,它会http在其内部表中查找协议,并得知它应该使用端口 80。
  5. 浏览器构建如下多层连接:

    • IP层:连接到 10.11.12.13
    • TCP 层:将数据包设置为目标端口 80
    • HTTP 层:为/hello.htm主机上的 URL 创建一个 HTTP 请求www.pippo.it(因为 at 的计算机10.11.12.13可能托管多个域,因此需要知道需要哪个)

      GET /hello.htm HTTP/1.1
      Host: www.pippo.it
      ...
      
      Run Code Online (Sandbox Code Playgroud)

    当然,我省略了 TCP 握手等的所有细节。

  6. 浏览器收到一个 HTTP 响应(分层在 TCP 之上,分层在 IP 之上等)包含以下内容 hello.htm

为了更好地衡量,我会提到浏览器现在检查该响应的内容,并确定所需的任何其他资源:图像、CSS、Javascript 等。然后它对每个这样的资源重复整个过程。

  • 第 3 步确实不是应用程序本身所做的事情。该应用程序仅使用诸如`getaddrinfo` 或`gethostbyname` 之类的东西来要求操作系统为其解析地址。此外,操作系统通常使用多种机制来尝试查找名称,而不仅仅是 DNS。(通常,除了 DNS 之外,至少还有 hosts 文件。) (4认同)