經過瀏覽器訪問一個 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 等文件,並最終將頁面展示在用戶面前。

相關文章
相關標籤/搜索