1. 程式人生 > >一文搞懂HTTP協議及相關常見面試題

一文搞懂HTTP協議及相關常見面試題

異常 dns 事務 轉換 etc post location hyper 手動

HTTP是什麽?

 HTTP協議也叫Hyper Text Transfer Protocol(超文本傳輸協議),工作在OSI參考模型的應用層,是一個基於請求與響應模式的無狀態的協議,同時也是基於TCP/IP協議來傳輸數據。

HTTP主要特點

  1、主要支持B/S模式:平常我們使用的瀏覽器可根據url向服務器發送請求,服務器拿到HTTP報文之後解析並作出響應,將數據傳輸回瀏覽器,TCP三次握手建立連接之後傳輸數據就是HTTP報文與其他的服務器資源

  2、簡單快速:客戶端向服務器請求服務時,只需要傳輸請求方法(比如:GET,POST,PUT等等)和路徑(即URL資源定位符)服務器收到就會將對應的資源和響應返回給客戶端

  3、靈活:HTTP允許傳輸任意數據對象,正在傳輸的類型由Content-Type加以標記。

  4、無連接:每次連接只處理一個請求。服務器處理完客戶的請求,並收到客戶的應答後,即斷開連接。采用這種方式可以節省傳輸時間。但是在HTTP1.1版本之後,在HTTP1.1中已經默認使用Connection: keep-alive,避免了連接建立和釋放的開銷,但服務器必須按照客戶端請求的先後順序依次回送相應的結果,以保證客戶端能夠區分出每次請求的響應內容。通過Content-Length字段來判斷當前請求的數據是否已經全部接收。不允許同時存在兩個並行的響應。但是無連接永遠是HTTP的特性,至於下層的TCP連接是否關閉已經不在HTTP管轄範圍之內,所以HTTP協議還是無連接的

  5、無狀態:HTTP協議是無狀態協議。無狀態是指協議對於事務處理沒有記憶能力。缺少狀態意味著如果後續處理需要前面的信息,則它必須重傳,這樣可能導致每次連接傳送的數據量增大。另一方面,在服務器不需要先前信息時它的應答就較快。

HTTP請求結構

技術分享圖片

  下面是我訪問https://www.baidu.com的HTTP請求報文

GET https://www.baidu.com/ HTTP/1.1\r\n
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\n
Accept-Encoding: gzip, deflate, br\r\n
Accept-Language: zh-CN,zh;q=0.9\r\n
Connection: keep-alive\r\n
Cookie: ***\r\n
Host: www.baidu.com\r\n
Upgrade-Insecure-Requests: 1\r\n
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36\r\n
\r\n
  下面是響應報文頭部字段名的含義   Accept:瀏覽器可接受的文件類型。   Accept-Charset:瀏覽器可接受的字符集。   Accept-Encoding:瀏覽器能夠進行解碼的數據編碼方式,比如gzip。Servlet能夠向支持gzip的瀏覽器返回經gzip編碼的HTML頁面。許多情形下這可以減少5到10倍的下載時間。   Accept-Language:瀏覽器所希望的語言種類,當服務器能夠提供一種以上的語言版本時要用到。   Authorization:授權信息,通常出現在對服務器發送的WWW-Authenticate頭的應答中。   Connection:表示是否需要持久連接。如果Servlet看到這裏的值為“Keep-Alive”,或者看到請求使用的是HTTP 1.1(HTTP 1.1默認進行持久連接),它就可以利用持久連接的優點,當頁面包含多個元素時(例如Applet,圖片),顯著地減少下載所需要的時間。要實現這一點,Servlet需要在應答中發送一個Content-Length頭,最簡單的實現方法是:先把內容寫入ByteArrayOutputStream,然後在正式寫出內容之前計算它的大小。   Content-Length:表示請求消息正文的長度。   Cookie:這是最重要的請求頭信息之一,某些網站為了辨別用戶身份、進行 session 跟蹤而儲存在用戶本地終端上的數據(通常經過加密)就是cookie。所以比較重要,不能隨意讓其他人獲取到自己在網頁上的Cookie   From:請求發送者的email地址,由一些特殊的Web客戶程序使用,瀏覽器不會用到它。   Host:初始URL中的主機和端口。   If-Modified-Since:只有當所請求的內容在指定的日期之後又經過修改才返回它,否則返回304“Not Modified”應答。   Pragma:指定“no-cache”值表示服務器必須返回一個刷新後的文檔,即使它是代理服務器而且已經有了頁面的本地拷貝。   Referer:包含一個URL,用戶從該URL代表的頁面出發訪問當前請求的頁面。   User-Agent:瀏覽器類型,如果Servlet返回的內容與瀏覽器類型有關則該值非常有用。   UA-Pixels,UA-Color,UA-OS,UA-CPU:由某些版本的IE瀏覽器所發送的非標準的請求頭,表示屏幕大小、顏色深度、操作系統和CPU類型。   但是瀏覽器不一定發所有的請求頭字段,而是選取需要的發送,每個網頁發送的請求頭字段都不一樣

HTTP響應報文結構

技術分享圖片

  下面是百度傳回來的響應報文

HTTP/1.1 200 OK\r\n
Bdpagetype: 2\r\n Bdqid: 0xd24a0cab000b1e6e\r\n Cache-Control: private\r\n Connection: Keep-Alive\r\n Content-Encoding: gzip\r\n Content-Type: text/html;charset=utf-8\r\n Date: Wed, 08 May 2019 03:23:24 GMT\r\n Expires: Wed, 08 May 2019 03:23:24 GMT\r\n Server: BWS/1.1\r\n Set-Cookie: ***\r\n Set-Cookie: ***\r\n Set-Cookie: ***\r\n
\r\n

  響應正文就是百度的前端界面代碼,最終瀏覽器會將這個前端展示給我們

下面是響應報文頭部字段名的含義:

  Allow 服務器支持哪些請求方法(如GET、POST等)。   Content-Encoding 文檔的編碼(Encode)方法。只有在解碼之後才可以得到Content-Type頭指定的內容類型。利用gzip壓縮文檔能夠顯著地減少HTML文檔的下載時間。Java的GZIPOutputStream可以很方便地進行gzip壓縮,但只有Unix上的Netscape和Windows上的IE 4、IE 5才支持它。因此,Servlet應該通過查看Accept-Encoding頭(即 request.getHeader("Accept-Encoding"))檢查瀏覽器是否支持gzip,為支持gzip的瀏覽器返回經gzip壓縮的HTML頁面,為其他瀏覽器返回普通頁面。   Content-Length 表示內容長度。只有當瀏覽器使用持久HTTP連接時才需要這個數據。如果你想要利用持久連接的優勢,可以把輸出文檔寫入ByteArrayOutputStram,完成後查看其大小,然後把該值放入Content-Length頭,最後通過byteArrayStream.writeTo(response.getOutputStream()發送內容。   Content-Type 表示後面的文檔屬於什麽MIME類型。Servlet默認為text/plain,但通常需要顯式地指定為text/html。由於經常要設置Content-Type,因此HttpServletResponse提供了一個專用的方法setContentType。   Date 當前的GMT時間。你可以用setDateHeader來設置這個頭以避免轉換時間格式的麻煩。   Expires 應該在什麽時候認為文檔已經過期,從而不再緩存它   Last-Modified 文檔的最後改動時間。客戶可以通過If-Modified-Since請求頭提供一個日期,該請求將被視為一個條件GET,只有改動時間遲於指定時間的文檔才會返回,否則返回一個304(Not Modified)狀態。Last-Modified也可用setDateHeader方法來設置。   Location 表示客戶應當到哪裏去提取文檔。Location通常不是直接設置的,而是通過HttpServletResponse的sendRedirect方法,該方法同時設置狀態代碼為302。   Refresh 表示瀏覽器應該在多少時間之後刷新文檔,以秒計。除了刷新當前文檔之外,你還可以通過setHeader("Refresh", "5; URL=http://host/path")讓瀏覽器讀取指定的頁面。註意這種功能通常是通過設置HTML頁面HEAD區的<META HTTP-EQUIV="Refresh" CONTENT="5;URL=http://host/path">實現,這是因為,自動刷新或重定向對於那些不能使用CGI或Servlet的HTML編寫者十分重要。但是,對於Servlet來說,直接設置Refresh頭更加方便。註意Refresh的意義是“N秒之後刷新本頁面或訪問指定頁面”,而不是“每隔N秒刷新本頁面或訪問指定頁面”。因此,連續刷新要求每次都發送一個Refresh頭,而發送204狀態代碼則可以阻止瀏覽器繼續刷新,不管是使用Refresh頭還是<META HTTP-EQUIV="Refresh" ...>。註意Refresh頭不屬於HTTP 1.1正式規範的一部分,而是一個擴展,但Netscape和IE都支持它。   Server 服務器名字。Servlet一般不設置這個值,而是由Web服務器自己設置。   Set-Cookie 設置和頁面關聯的Cookie。Servlet不應使用response.setHeader("Set-Cookie", ...),而是應使用HttpServletResponse提供的專用方法addCookie。參見下文有關Cookie設置的討論。   WWW-Authenticate 客戶應該在Authorization頭中提供什麽類型的授權信息?在包含401(Unauthorized)狀態行的應答中這個頭是必需的。例如,response.setHeader("WWW-Authenticate", "BASIC realm=\"executives\"")。註意Servlet一般不進行這方面的處理,而是讓Web服務器的專門機制來控制受密碼保護頁面的訪問(例如.htaccess)。 下面是常見狀態碼的含義:

  1XX:接受的請求正在處理
  2XX:請求正常處理完畢
    200 OK:請求已經正常處理
    204 No Content:請求處理成功但沒有資源返回
    206 Partial Content:是對資源的一部分請求,即響應報文中包含Content-Range指定的範圍實體
  3XX:需要進行附加操作以完成請求
    301 Moved Permanently:也就是URI在服務器端更新,客戶端也要進行書簽引用的變更
    302 Found:只是臨時重定向和301狀態碼有些相似,但是301是永久性的
    303 See Other:303和302有著相同的功能,但303狀態碼表示客戶端需要用到GET的方式進行請求
    304 Not Modified:表示客戶端發送附帶條件的請求時,服務器端允許請求訪問資源,但是請求未能滿足服務器所設置的條件
    307 Temporary Redirect:臨時重定向。302有相同的含義。307會遵照瀏覽器的標準。
  4XX:服務器無法處理請求,可以理解為客戶端發送的請求信息有誤
    400 Bad Request:表示請求報文中存在語法錯誤
    401 Unauthorized:表示發送的請求需要有通過HTTP的認證信息,若之前有過請求,這表示請求失敗
    403 Forbidden:表明對請求資源的訪問被服務器拒絕了,但如果想做說明的話,需要在實體的主體部分對原因進行描述
    404 Not Found:服務器中沒有找到資源,或者拒絕訪問又不想說明理由的時候
  5XX:服務器處理請求出錯。錯在服務器這邊
    500 Internal Server Error:表明服務器端在執行請求的時候出現了錯誤
    503 Service Unavailable:表示服務器正處在超負載或正在進行停機維護

HTTP請求響應步驟

  1、客戶端(通常是瀏覽器)連接到Web服務器(一般默認端口號是80),這時候會建立一個套接字連接   2、發送HTTP請求,通過套接字,客戶端就可以向Web服務器發送一個請求報文   3、服務器接收請求並返回HTTP響應,也就是Web服務器解析請求定位請求資源,而後服務器再將資源副本寫到TCP套接字由客戶端讀取   4、如果連接模式為close,那麽服務器會主動關閉連接,而客戶端是被動關閉連接,若連接模式為keep-alive那麽連接就會保持一段時間   5、最後這一步就是瀏覽器解析HTML內容,首先會檢查狀態行看是否成功,然後解析每一個響應頭,最後就是解析前端HTML代碼。瀏覽器會根據狀態碼來查看是否要接著解析,比如出現404狀態碼,瀏覽器就會展示異常給我們,同樣這時它是拿不到響應正文的。

三道面試常考題

1、在瀏覽器鍵入URL,按下回車之後的流程是什麽?

  (1)、DNS解析:瀏覽器會根據URL逐層查詢DNS服務器緩存,解析出URL中的域名所對應的IP地址。DNS緩存分別有瀏覽器緩存,系統緩存,路由器緩存,IPS服務器緩存,根域名服務器緩存,頂級域名服務器緩存。從上面的哪一級緩存查詢到後直接返回IP地址,不再查詢。   (2)、TCP連接:在得到服務器的IP地址之後,就會嘗試和服務器建立連接(具體內容可以看之前的博文TCP協議三次握手和四次握手)   (3)、發送HTTP請求:在瀏覽器和服務器之間建立好連接之後,瀏覽器就會發送HTTP請求報文   (4)、服務器處理請求並返回HTTP報文:服務器返回給瀏覽器帶有HTML的響應報文   (5)、瀏覽器解析渲染頁面   (6)、瀏覽器釋放連接,即TCP四次揮手。 2、GET和POST區別   先來看看請求方法有哪些:   OPTIONS:返回服務器所支持的請求方法   GET:向服務器獲取指定資源   HEAD:與GET一致,但是只返回響應頭,不返回響應正文   POST:向服務器提交數據,數據放在請求體裏PUT 與POST相似,只是具有冪等特性,一般用於更新DELETE 刪除服務器指定資源   TRACE:回顯服務器端收到的請求,測試的時候會用到這個   CONNECT:預留,暫無使用   而GET和POST作為最常用的兩個請求方法,究竟區別在哪?   1、最直觀的就是GET會將請求的參數放在URL中,由於URL有長度限制,所以參數不能太多,而POST的參數是放在請求報文的正文中,長度沒有限制。   2、GET方式主要是對數據庫進行查詢,所以GET是符合冪等性(對數據庫無論操作多少次返回的結果是一樣的)和安全性(不修改數據庫),而POST主要用於讓數據庫增加數據或者刪除,修改數據,所以會有一定的安全性問題,需要對POST提交的參數做一些安全性檢驗。   3、GET方式還能被緩存被存儲,GET請求的URL會保存在瀏覽器的歷史記錄中,而緩存也是GET請求被廣泛應用的根本,而POST方式除非手動設置,不然不會被緩存。   4、GET方式下產生一個TCP數據包,POST產生兩個數據包。對於GET方式,瀏覽器會把HTTP請求報文發出去,服務器響應200之後返回響應報文,而POST則是瀏覽器先發HTTP請求頭,服務器響應100 continue之後瀏覽器再發從請求正文過去,服務器響應200並返回數據(但是在Firefox瀏覽器POST就只發一次數據包) 3、Cookie和Session的區別   前面我們說過HTTP是無狀態的,也就是沒有記憶功能,那我們的自動登錄都是怎麽樣實現的呢?主要是兩種   第一種方法(瀏覽器):使用Cookie。Cookie是服務器發給瀏覽器的特殊信息,並會以文本形式存在瀏覽器中,所以我們點擊瀏覽器的清除記錄,往往會問我們是否清理Cookie,當清理之後下次再訪問網頁就會需要我們重新登錄。如果瀏覽器中存在Cookie,那麽提交請求就會一起提交過去服務器在接收到後就會解析Cookie生成與客戶端相對應的內容,實現自動登錄,Cookie帶有我們的比較重要信息,所以一般不要給被人獲取   第二種方法(服務器):使用Session。Session是在服務器上保存的信息,當服務器需要為客戶創建Session的時候,就會解析客戶端請求查看請求是否包含session id,如果包含那麽就表明此前已經為客戶端創建過session,不包含則創建一個對應的session id,而後回發給客戶端,使得客戶端下次能帶有session id。然後按需保存狀態   所以最終的區別總結起來就是:Cookie數據存放在客戶瀏覽器上,Session數據存放在服務器上,Session相對應Cookie安全,而使用Cookie會給服務器減負 彩蛋: 在訪問百度首頁,使用瀏覽器的開發者工具查看console的時候會發現 技術分享圖片

這也算我寫這篇博客的一個收獲吧

一文搞懂HTTP協議及相關常見面試題