添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

浏览器解析 URL

一个标准的 URL 语法通常都建立在由 9 部分构成的通用格式上,浏览器会从用户输入的 URL 字符串中解析对应的内容:

<schema>://<user>:<password>@<host>:<port>;<params>?<query>#<frag>
复制代码

其中比较重要的有:

  • schema——协议版本
  • host——主机地址
  • port——端口号
  • path——文件路径
  • query——即 query_string 查询字符串
  • DNS 域名解析

    如果上面提到的 host 部分为 域名 ,则需要通过 DNS 对其进行解析。

    查找本地 host 文件

    用户可以在本地的 host 文件中指定域名和 IP 地址的对应关系,所以浏览器会先去本地的 host 文件中寻找是否存在对应的 IP 地址,如果存在,则向该地址发送请求。

    DNS 解析

  • 查询 本地 域名服务器
  • 本地 域名服务器将查询报文转发到 域名服务器并进行查询
  • 域名服务器根据具体的域名地址,向 本地 域名服务器返回 顶级 域名服务器地址
  • 本地 域名服务器向 顶级 域名服务器发送查询请求
  • 顶级 域名服务器向 本地 域名服务器返回 权限 域名服务器地址
  • 本地 域名服务器向 权限 域名服务器发送查询请求
  • 最终,我们通过 DNS 解析获得了主机的 IP 地址

    建立 TCP 连接

    三次握手的过程是老生常谈了,资料比较多,这里就不具体赘述了,只列出大致过程:

  • 客户端发送 SYN 报文,请求建立连接
  • 服务端发送 ACK 报文和 SYN 报文,表示同意客户端的建立连接请求,同时自己也请求建立连接
  • 客户端发送 ACK 报文,表示请求已收到
  • 使用 APR 协议定位目标地址

    在以太网中,一台主机要把数据帧发送到同一局域网上的另一台主机时,设备驱动程序必须知道以太网地址才能发送数据。而我们只知道IP地址,这时就需要采用 ARP 协议将 IP 地址映射为以太网地址。 在发送第一个 SYN 报文时,IP 层会通过 ARP 协议查询出目标主机的 MAC 地址。 ( TCP/IP协议——ARP详解

    第一次握手 时发送的第一个 SYN 报文首先会通过 connect() 函数到达 IP 层,之后 IP 层会通过查询路由表获取目标主机的 MAC 地址并将其缓存,然后该 MAC 地址会被通过 send() 函数交给网络接口进行封装,最终将数据发送出去。
    PS:引用资料的文章非常详细的解释了不同情况下该过程的工作细节,建议认真阅读一遍。

    建立 SSL 隧道

    如果请求使用的是 HTTPS 协议,则在建立 TCP 连接后,需要通过 四次握手 在其之上再建立一条加密隧道,即 SSL

  • 发送 协议版本号
  • 发送支持的加密方法
  • 生成 随机数 1 client random )并传输给服务端
  • 选择并发送要使用的加密方法
  • 发送 数字证书
  • 生成 随机数 2 server random )并传输给客户端
  • 验证 数字证书
  • 生成一个 随机数 3 premaster secret ),使用 公钥 对其进行加密后传输给服务端
  • 使用 client random server random premaster secret 生成 会话密钥 session key
  • 使用 私钥 对加密字符串进行解密,获得 premaster secret
  • 使用 client random server random premaster secret 生成 会话密钥 session key
  • 四次握手通过 非对称加密 的方式使客户端和服务端获得并持有相同的 session key ,并通过该 key 值对之后的会话过程进行 对称加密

    发送 HTTP(s)请求

    浏览器使用前两步获得的信息构造 请求报文 ,并通过第三步建立起来的 TCP 连接向服务端发送 HTTP 请求。 其中, 请求报文 的基本格式为:

    <method><request-URL><version>  
    <headers>  
    <entity-body>
    复制代码

    这三部分分别为 起始行 首部 主体 ,通过浏览器请求发起的默认为 GET 请求,所以没有 主体 部分。
    下面展示了一个假想的 HTTP 报文,其中第一行为 起始行 ,二三行为 首部

    GET /index.html HTTP/1.1
    Accept: text/html
    Host: www.foo.com
    复制代码

    服务端代理处理请求

    服务端代理 即为 nginx apache 等服务器软件,它们会根据配置文件 将请求映射为服务器上具体的文件 ,并根据文件类型对其进行处理返回。

    直接返回静态文件(.html)

    如果文件是类型为 .html .txt .xml 的静态文件,则只需将其内容作为响应的 entity-body 直接返回给客户端。

    解析动态文件(.php)

    如果文件类型为 .php .jsp .asp 等动态文件,则需要对其进行解析。这里我们只讲解对 .php 文件的操作,以 nginx 服务器为例。

  • nginx 得知要处理的为 .php 文件
  • nginx 调用自己的 Fast-CGI 模块,构造 Fast-CGI 请求
  • nginx 向 PHP-FPM 发送 Fast-CGI 请求, 此时 nginx 相当于一个反向代理服务器
  • PHP-FPM 的 master 进程 收到请求
  • master 将请求分配给特定的 worker 进程
  • worker 进程使用内嵌的 PHP-CGI 解释器对 PHP 文件进行解析,返回结果并生成对 nginx 的响应
  • nginx 获得来自 PHP-FPM 的响应,即得到静态文件
  • 服务端代理响应请求

    nginx 生成响应报文,返回给客户端。响应报文和请求报文只有起始行的语法有所不同:

    <version><status><reason-phrase>
    <headers>
    <entity-body>
    复制代码

    关闭 TCP 连接

    老生常谈喜闻乐见的四次挥手环节,因为相关资料实在是太多了,这里也不具体赘述了,只列出大致过程:

  • 客户端发送 FIN 报文,表示自己的所有数据已传输完毕
  • 服务端返回 ACK 报文,表示请求已收到
  • 服务端发送 FIN 报文,表示自己的所有数据也都已经传输完毕
  • 服务端返回 ACK 报文,表示请求已收到,并进入 TIME_WAIT 状态
  • 客户端对返回的文件进行解析