经过浏览器访问一个 PHP 文件时发生了什么?

浏览器解析 URL

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

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

其中比较重要的有:html

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

DNS 域名解析

若是上面提到的 host 部分为域名,则须要经过 DNS 对其进行解析。nginx

查找本地 host 文件

用户能够在本地的 host 文件中指定域名和 IP 地址的对应关系,因此浏览器会先去本地的 host 文件中寻找是否存在对应的 IP 地址,若是存在,则向该地址发送请求。apache

DNS 解析

  • 查询本地域名服务器
  • 本地域名服务器将查询报文转发到域名服务器并进行查询
  • 域名服务器根据具体的域名地址,向本地域名服务器返回顶级域名服务器地址
  • 本地域名服务器向顶级域名服务器发送查询请求
  • 顶级域名服务器向本地域名服务器返回权限域名服务器地址
  • 本地域名服务器向权限域名服务器发送查询请求

最终,咱们经过 DNS 解析得到了主机的 IP 地址浏览器

创建 TCP 链接

三次握手

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

  1. 客户端发送 SYN 报文,请求创建链接
  2. 服务端发送 ACK 报文和 SYN 报文,表示赞成客户端的创建链接请求,同时本身也请求创建链接
  3. 客户端发送 ACK 报文,表示请求已收到

使用 APR 协议定位目标地址

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

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

创建 SSL 隧道

若是请求使用的是 HTTPS 协议,则在创建 TCP 链接后,须要经过四次握手在其之上再创建一条加密隧道,即 SSL网络

四次握手

  1. 客户端:
    • 发送协议版本号
    • 发送支持的加密方法
    • 生成随机数 1client random)并传输给服务端
  2. 服务端:
    • 选择并发送要使用的加密方法
    • 发送数字证书
    • 生成随机数 2server random)并传输给客户端
  3. 客户端:
    • 验证数字证书
    • 生成一个随机数 3premaster secret),使用公钥对其进行加密后传输给服务端
    • 使用 client randomserver randompremaster secret 生成 会话密钥session key
  4. 服务器:
    • 使用私钥对加密字符串进行解密,得到 premaster secret
    • 使用 client randomserver randompremaster secret 生成 会话密钥session key

四次握手经过非对称加密的方式使客户端和服务端得到并持有相同的 session key,并经过该 key 值对以后的会话过程进行对称加密session

发送 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
复制代码

服务端代理处理请求

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

直接返回静态文件(.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 链接

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

  1. 客户端发送 FIN 报文,表示本身的全部数据已传输完毕
  2. 服务端返回 ACK 报文,表示请求已收到
  3. 服务端发送 FIN 报文,表示本身的全部数据也都已经传输完毕
  4. 服务端返回 ACK 报文,表示请求已收到,并进入 TIME_WAIT 状态

客户端对返回的文件进行解析

浏览器会解析返回的 HTML / CSS / JS 等文件,并最终将页面展示在用户面前。

相关文章
相关标签/搜索