經 常看到HTTP用戶端與伺服器端互動原理的各種版本的文章,但是專業術語太多,且流程過于複雜,不容易消化。于是就按照在 Servlet 裡面的内容大緻做了一些穿插。本來 連 Tomcat 容器 和 Servlet 的生命周期也準備在這裡一起寫的,但怕過去龐大,于是就簡單的 引用了一些 Servlet 對象。這樣的一個整個流程看下來,相信至少在了解 HTTP協定 和 request 和 response 是如何完成從請求到生成響應結果回發的。在後續的一些文章裡會專門講一講 Tomcat 和 Servlet 是如何處理請求和完成響應的,更多的是說明Servlet 的生命周期。
HTTP介紹
1.HTTP是一種超文本傳送協定(HyperText Transfer Protocol),是一套計算機在網絡中通信的一種規則。在TCP/IP體系結構中,HTTP屬于應用層協定,位于TCP/IP協定的頂層。
2.HTTP是一種無狀态的的協定,意思是指 在Web 浏覽器(用戶端)和 Web 伺服器之間不需要建立持久的連接配接。整個過程就是當一個用戶端向伺服器端發送一個請求(request),然後Web伺服器傳回一個響應 (response),之後連接配接就關閉了,在服務端此時是沒有保留連接配接的資訊。
3.HTTP 遵循 請求/響應(request/response) 模型的,所有的通信互動都被構造在一套請求和響應模型中。
4.浏覽WEB時,浏覽器通過HTTP協定與WEB伺服器交換資訊,Web伺服器向Web浏覽器傳回的檔案都有與之相關的類型,這些資訊類型的格式由MIME定義。
HTTP定義的事務處理由以下四步組成:
1.建立連接配接
2.用戶端發送HTTP請求頭
3.伺服器端響應生成結果 回發
4.伺服器端關閉連接配接,用戶端解析回發響應頭,恢複頁面
###############################################################################################
1.建立連接配接:以下用我的另一篇文章的位址做為例子
Servlet容器(Tomacat)介紹及配置
[url]http://blog.csdn.net/[/url]lvpin/archive/2007/06/09/1645767.aspx
用戶端,也就是我請求一個位址時 即打開了到 web 伺服器的HTTP端口的一個套接字。因為在網絡中間作為傳遞資料的實體媒體就是網線,資料實質上是通過IO流進行輸出和輸入,這就不難了解我們為什麼在寫 一個Servlet的時候要引用 import java.io.*; 的原因 ,包括我們在向用戶端回發結果的時候要用到 PrintWriter 對象的println()方法。
比如我在這裡請求CSDN社群的一個位址[url]http://blog.csdn.net[/url],
實際上首先要請求這個位址,以及一個端口80(8080)[url]http://blog.csdn.net:80[/url] 80可以不寫,是因為浏覽器網頁服務預設的端口号是 80.
在Java底層代碼中是這樣實作的,隻不過它們已經幫我們做了。
Soceet socket=new Socket("blog.csdn.net",8080);
InputStream in=socket.getInputStream();
OutputStream out=socket.getOutputStream();
一旦建立了TCP連接配接,Web浏覽器就會向Web伺服器發送請求指令,是一個ASCII文本請求行,後跟0個或多個HTTP頭标,一個空行和實作請求的任意資料。
四個部分:請求行,請求頭标,空行和請求資料
1)請求行由三個标記組成 請求方法 請求URL HTTP版本 中間用空格分開
例如: GET lvpin/archive/2007/06/09/1645767.aspx HTTP/1.1
HTTP規範定義了8種可能的請求方法:(最常見的就是 GET 和 POST 兩種方法)
GET 檢索URI中辨別資源的一個簡單請求
HEAD 與GET方法相同,伺服器隻傳回狀态行和頭标,并不傳回請求文檔
POST 伺服器接受被寫入用戶端輸出流中的資料的請求
PUT 伺服器儲存請求資料作為指定URI新内容的請求
DELETE 伺服器删除URI中命名的資源的請求
OPTIONS 關于伺服器支援的請求方法資訊的請求
TRACE Web伺服器回報Http請求和其頭标的請求
CONNECT 已文檔化但目前未實作的一個方法,預留做隧道處理
2).請求頭标:由key :value 健值組成,每行一對。請求頭标 通知伺服器有關用戶端的功能和辨別。
HOST 請求的哪一個伺服器端位址,主位址 ,比如 我現在所在的CSDN blog.csdn.net/
User-Agent 使用者即用戶端可以使用的浏覽器 ,如 : Mozilla/4.0
Accept 即用戶端可以接受的MIME 類型清單,如p_w_picpath/gif text/html, application/msword
Content-Length 隻适用于POST請求,以位元組給出POST資料的尺寸
3)空行 發送回車符和退行,通知伺服器以下不再有頭标。
4)請求資料 : 使用POST傳送資料,最常使用的是Content-Type和Content-Length頭标。
總結以上 我們可以這樣寫出一個标準的 HTTP請求
POST /lvpin/archive/2007/06/09/1645767.aspx HTTP1.1
HOST: blog.csdn.net/
User-Agent :Mozilla/4.0
Accpt: p_w_picpath/gif,text/html,application/pdf,p_w_picpath/png...
key=value&key=value&key=value.....................................(POST()請求的資料)
那麼,這上面的一個例子說明的就是
我要去通路的伺服器端的位址是blog.csdn.net/ 它下面的資源 /lvpin/archive/2007/06/09/1645767.aspx
連起來就是 [url]http://blog.csdn.net/lvpin/archive/2007/06/09/1645767.aspx[/url]
這個頁面用的是 HTTP1.1 規範 我的浏覽器版本是Mozilla/4.0
可以支援的MIME格式為 p_w_picpath/gif,text/html,application/pdf,p_w_picpath/png...等等
這個MIME格式我們在 response.setContentType("text/html;charset=gb2312");
或者在一個 <%@ page contentType="text/html;charset=gb2312"%>
或者<meta .....contentType="text/html;charset=gb2312"..>總能見到
那麼在這裡如何了解 GET 和 POST 最直覺的差別,最明顯的就是 GET方法将資料的請求跟在了所請求的URL後面,也就是 在請求行裡面我們是這麼樣來做的:
GET lvpin/archive/2007/06/09/1645767.aspx?key=value&key=value&key=value......HTTP1.1
也實際上就是 用 GET 如此傳遞資料 :
[url]http://blog.csdn.net/[/url] lvpin/archive/2007/06/09/1645767.aspx?name=simon&password=simonlv........
3.伺服器端接受請求,處理資料後生成響應傳回資料到用戶端 (部分Servlet 内容穿插)
Web 伺服器 解析請求,定位指定的資源[url]http://blog.csdn.net/lvpin/archive/2007/06/09/1645767.aspx[/url]
1)根據在 請求時的 GET/POST 來按照響應的 doGet() /doPost()方法來處理(有可能是一些業務邏輯,也有可能是一些驗證等等,也有可能是一些資料查詢,送出等等)其有效的資料就來源于name=simon&password=simonlv,還有 其它的一些封裝在 request 對象中的資料資源。
2)處理請求之後,由 response 對象得到 PriterWriter 輸出流對象out ,通過 out.println () 将資料以 在用戶端送出過的采用的Accpt: 中形式的一種 如 按照 response.setcontentType("text/html;charset=gb2312' )的格式輸出流。
它的響應資訊與請求資訊非常類似,其差別就在于 我們在請求階段的請求行被狀态行給替換了,再來看響應頭
一個響應由四個部分組成;狀态行、響應頭标、空行、響應資料
1.狀态行:狀态行由三個标記組成:HTTP版本、響應代碼和響應描述。
HTTP1.1 100 continue ------繼續追加後繼内容
HTTP/1.1 200 OK --------一切正常
HTTP1.1 301 Moved Permanently ---請求的文檔在其它地方,會自動連接配接
HTTP1.1 403 Forbidden -------絕對拒絕你通路這個資源,不管授權沒有
HTTP1.1 400 Bad Request -----用戶端請求中的不良文法
HTTP1.1 404 Not Found ---最常見,絕對是大名鼎鼎的找不到
HTTP響應碼:
1xx:提示性資訊,告訴用戶端應該對某些其它的動作作出響應
2xx:這些就代表了請求成功
3xx:重定向,為了完成請求,必須進一步執行的動作
4xx:用戶端錯誤
500-599:伺服器端的錯誤
2.響應頭标:像請求頭标一樣,它們指出伺服器的功能,辨別出響應資料的細節。
Date: Sat, 31 Dec 2005 23:59:59 GMT --響應生成的日期和時間
ContentType: text/html;charset=gb2312'
Content-Length: 122 ---響應中的位元組數,隻在浏覽器使用永久(Keep-alive)HTTP連接配接時需要。
3.空行:最後一個響應頭标之後是一個空行,發送回車符和退行,表明伺服器以下不再有頭标。
4.響應資料:HTML文檔和圖像等,也就是HTML本身。out.println("<html>").......寫出的。。。
<html>
<head>
<title>Welcom to simon lv 's home</title>
</head>
<body>
<!-- 這裡是具體的内容,看到了這裡
相信大家對 HTTP 工作原理和伺服器互動過程已經很清楚了吧
-->
</body>
</html>
1)浏覽器先解析狀态行,檢視請求是否成功的狀态代碼--HTTP響應碼:404 400 200 ....
3) 讀取響應資料HTML,根據它的文法标簽<html></html>等和内容恢複标準的HTML格式頁面或者其它。
4)一個HTML 文檔可能包含其它的需要被載入的資源,浏覽器會識别,并對這些資源再進行額外的請求,這個過程可以一直循環到所有的資料都按照響應頭标中規定的格式恢複到頁面中。
5)資料傳送完畢,伺服器端關閉連接配接,即無狀态協定。
寫了很長時間,估計裡面也有些沒有表達清楚的地方,但是整個流程可以清晰的展現,對于大家了解HTTP請求頭和響應頭的内容以及他們之間的關