從前端發起請求到背景的整個過程,是一個面試中經常遇到的問題。大概的流程想必有一點基礎的人都明白,但是要細說,卻未必能一一道出來,曾經老師教過的知識也都差不多忘幹淨了。是以,我上網找了點資料,加上自己的了解,做個記錄。
********************************************************** 華麗的分割線 ******************************************************************
一、HTTP是什麼
http(HyperText Transfer Protocol),超文本傳輸協定,是網際網路上應用最廣泛的一種網絡協定,所有www檔案都必須遵守的一個标準,是以 ASCII 碼傳輸,建立在 TCP/IP 協定之上的應用層規範。說白了,就是大家都約好互相之間按照一種固定的規則來進行通訊。
http也可以說成是一種用戶端和應答伺服器端請求和應答的标準(TCP)。通過使用浏覽器或其他工具(如google的Postman),用戶端發起一個到應答伺服器上指定端口(如Tomcat的8080或jmx的1099等)的http請求,或者反過來,伺服器給用戶端發送一個回應。在用戶端和應答伺服器端可能存在多個中間層,比如代理、網關或者隧道。
二、HTTP請求封包
http請求封包是指用戶端到伺服器端的消息,用戶端通過發送http請求向伺服器請求對資源的通路。包括三個部分:請求行、請求頭部、請求資料。請求方法有 OPTIONS、GET、HEAD、POST、PUT、DELETE、TRACE、CONNECT 這幾種。
1.請求行:包含請求方法、uri和協定的版本,用空格分隔,例如:GET/sample.jsp HTTP/1.1
2.請求頭部:包含有關用戶端環境及請求正文的資訊,如請求正文長度、浏覽器所用編碼格式等,例如;
Accept:image/gif.image/jpeg.*/*Accept-Language:zh-cnConnection:Keep-AliveHost:localhostUser-Agent:Mozila/4.0(compatible:MSIE5.01:Windows NT5.0)Accept-Encoding:gzip,deflate
3.請求資料:即用戶端發送給伺服器的内容,可為空(GET請求就沒有請求資料),例如:username=jinqiao&password=1234
PS:1.請求頭部和請求資料之間必須有空行,用以區分。
2.最常用的請求頭部是Content-Type(請求編碼方式)和Content-Length(請求資料長度),例如:
Content-Type: application/x-www-form-urlencodedContent-Length: 35
三、HTTP應答封包
http應答封包是指伺服器回應http請求,發送給用戶端的消息。也包括三個部分:狀态行、響應頭部、響應資料。
1 狀态行:協定版本、狀态碼、簡要描述,例如:HTTP/1.1 200 OK
2 響應頭部:必須指明Content-Type,其他可選,例如:Content-Type: text/plain
3 響應資料:即伺服器回應用戶端的内容。
PS:常見狀态碼
1xx:訓示資訊--表示請求已接收,繼續處理。
2xx:成功--表示請求已被成功接收、了解、接受。
3xx:重定向--要完成請求必須進行更進一步的操作。
4xx:用戶端錯誤--請求有文法錯誤或請求無法實作。
5xx:伺服器端錯誤--伺服器未能實作合法的請求。
四、HTTP請求與響應步驟
http請求和響應,說白了就是計算機之間的問答對話。http請求是提問者,http響應是回答者。詳細步驟如下圖所示。

1 建立連接配接
先解析DNS,把localhost變成ip(127.0.0.1),然後根據127.0.0.1和端口号8080(沒有端口号則使用預設的端口)建立socket。也可以了解為通過“三次握手”建立TCP連接配接,确定通訊正常。
2 發送請求指令
socket建立好之後,用戶端開始向web伺服器發送請求指令(GET/POST等)。
3 發送請求頭(和請求正文如果有)
用戶端先發送與自身相關的資訊,再發送空行表示請求頭發送完畢,如果是post則繼續發送請求正文。
4 回傳狀态行
應答第一步,發送協定版本和狀态碼(200、503、404等)
5 回傳應答頭
應答第二步,先發送自身相關資訊、Content-Type(必須)及被請求的文檔,在發送空行寶石應答頭發送完畢。
6 回傳應答正文
應答第三步,根據應答頭的Content-Type指定的格式發送應答正文。
7 關閉連接配接
一次‘會話’完成,如果設定了Connection:keep-alive則TCP連接配接不關閉,否則關閉連接配接。
五、TCP/IP協定
TCP/IP協定模型(Transmission Control Protocol/Internet Protocol),包含了一系列構成網際網路基礎的網絡協定,是Internet的核心協定,通過20多年的發展已日漸成熟,并被廣泛應用于區域網路和廣域網中,目前已成為事實上的國際标準。TCP/IP協定簇是一組不同層次上的多個協定的組合,通常被認為是一個四層協定系統,與OSI的七層模型相對應。
HTTP協定就是基于TCP/IP協定模型來傳輸資訊的。
1 鍊路層
也稱作資料鍊路層或網絡接口層(在第一個圖中為網絡接口層和硬體層),通常包括作業系統中的裝置驅動程式和計算機中對應的網絡接口卡。它們一起處理與電纜(或其他任何傳輸媒介)的實體接口細節。ARP(位址解析協定)和RARP(逆位址解析協定)是某些網絡接口(如以太網和令牌環網)使用的特殊協定,用來轉換IP層和網絡接口層使用的位址。
2 網絡層
也稱作網際網路層(在第一個圖中為網際層),處理分組在網絡中的活動,例如分組的選路。在TCP/IP協定族中,網絡層協定包括IP協定(網際協定),ICMP協定(Internet網際網路控制封包協定),以及IGMP協定(Internet組管理協定)。
IP是一種網絡層協定,提供的是一種不可靠的服務,它隻是盡可能快地把分組從源結點送到目的結點,但是并不提供任何可靠性保證。同時被TCP和UDP使用。TCP和UDP的每組資料都通過端系統和每個中間路由器中的IP層在網際網路中進行傳輸。
ICMP是IP協定的附屬協定。IP層用它來與其他主機或路由器交換錯誤封包和其他重要資訊。IGMP是Internet組管理協定。它用來把一個UDP資料報多點傳播到多個主機。
3 傳輸層
主要為兩台主機上的應用程式提供端到端的通信。在TCP/IP協定族中,有兩個互不相同的傳輸協定:TCP(傳輸控制協定)和UDP(使用者資料報協定)。
TCP為兩台主機提供高可靠性的資料通信。它所做的工作包括把應用程式交給它的資料分成合适的小塊交給下面的網絡層,确認接收到的分組,設定發送最後确認分組的逾時時鐘等。由于運輸層提供了高可靠性的端到端的通信,是以應用層可以忽略所有這些細節。為了提供可靠的服務,TCP采用了逾時重傳、發送和接收端到端的确認分組等機制。
UDP則為應用層提供一種非常簡單的服務。它隻是把稱作資料報的分組從一台主機發送到另一台主機,但并不保證該資料報能到達另一端。一個資料報是指從發送方傳輸到接收方的一個資訊單元(例如,發送方指定的一定位元組數的資訊)。UDP協定任何必需的可靠性必須由應用層來提供。
4 應用層
應用層決定了向使用者提供應用服務時通信的活動。TCP/IP 協定族内預存了各類通用的應用服務。包括 HTTP,FTP(File Transfer Protocol,檔案傳輸協定),DNS(Domain Name System,域名系統)服務。
當應用程式用TCP傳送資料時,資料被送入協定棧中,然後逐個通過每一層直到被當作一串比特流送入網絡。其中每一層對收到的資料都要增加一些首部資訊(有時還要增加尾部資訊),該過程如圖所示。
當目的主機收到一個以太網資料幀時,資料就開始從協定棧中由底向上升,同時去掉各層協定加上的封包首部。每層協定盒都要去檢查封包首部中的協定辨別,以确定接收資料的上層協定。這個過程稱作分用(Demultiplexing)。協定是通過目的端口号、源I P位址和源端口号進行解包的。
通過以上步驟我們從TCP/IP模型的角度來了解了一次HTTP請求與響應的過程。下面這張圖更清楚明白:
六、TCP三向交握
第一次握手
建立連接配接。用戶端發送連接配接請求封包段,将SYN位置為1,Sequence Number為x;然後,用戶端進入SYN_SEND狀态,等待伺服器的确認;
第二次握手
伺服器收到SYN封包段。伺服器收到用戶端的SYN封包段,需要對這個SYN封包段進行确認,設定Acknowledgment Number為x+1(Sequence Number+1);同時,自己自己還要發送SYN請求資訊,将SYN位置為1,Sequence Number為y;伺服器端将上述所有資訊放到一個封包段(即SYN+ACK封包段)中,一并發送給用戶端,此時伺服器進入SYN_RECV狀态;
第三次握手
用戶端收到伺服器的SYN+ACK封包段。然後将Acknowledgment Number設定為y+1,向伺服器發送ACK封包段,這個封包段發送完畢以後,用戶端和伺服器端都進入ESTABLISHED狀态,完成TCP三向交握。
為什麼要三次握手
為了防止已失效的連接配接請求封包段突然又傳送到了服務端,因而産生錯誤。
具體例子:“已失效的連接配接請求封包段”的産生在這樣一種情況下:client發出的第一個連接配接請求封包段并沒有丢失,而是在某個網絡結點長時間的滞留了,以緻延誤到連接配接釋放以後的某個時間才到達server。本來這是一個早已失效的封包段。但server收到此失效的連接配接請求封包段後,就誤認為是client再次發出的一個新的連接配接請求。于是就向client發出确認封包段,同意建立連接配接。假設不采用“三次握手”,那麼隻要server發出确認,新的連接配接就建立了。由于現在client并沒有發出建立連接配接的請求,是以不會理睬server的确認,也不會向server發送資料。但server卻以為新的運輸連接配接已經建立,并一直等待client發來資料。這樣,server的很多資源就白白浪費掉了。采用“三次握手”的辦法可以防止上述現象發生。例如剛才那種情況,client不會向server的确認發出确認。server由于收不到确認,就知道client并沒有要求建立連接配接。”
七、四次揮手
第一次分手
主機1(可以使用戶端,也可以是伺服器端),設定Sequence Number,向主機2發送一個FIN封包段;此時,主機1進入FIN_WAIT_1狀态;這表示主機1沒有資料要發送給主機2了;
第二次分手
主機2收到了主機1發送的FIN封包段,向主機1回一個ACK封包段,Acknowledgment Number為Sequence Number加1;主機1進入FIN_WAIT_2狀态;主機2告訴主機1,我“同意”你的關閉請求;
第三次分手
主機2向主機1發送FIN封包段,請求關閉連接配接,同時主機2進入LAST_ACK狀态;
第四次分手
主機1收到主機2發送的FIN封包段,向主機2發送ACK封包段,然後主機1進入TIME_WAIT狀态;主機2收到主機1的ACK封包段以後,就關閉連接配接;此時,主機1等待2MSL後依然沒有收到回複,則證明Server端已正常關閉,那好,主機1也可以關閉連接配接了。
為什麼要四次分手
TCP協定是一種面向連接配接的、可靠的、基于位元組流的運輸層通信協定。TCP是全雙工模式,這就意味着,當主機1發出FIN封包段時,隻是表示主機1已經沒有資料要發送了,主機1告訴主機2,它的資料已經全部發送完畢了;但是,這個時候主機1還是可以接受來自主機2的資料;當主機2傳回ACK封包段時,表示它已經知道主機1沒有資料發送了,但是主機2還是可以發送資料到主機1的;當主機2也發送了FIN封包段時,這個時候就表示主機2也沒有資料要發送了,就會告訴主機1,我也沒有資料要發送了,之後彼此就會愉快的中斷這次TCP連接配接。