Netty源碼解析之 java網絡編程篇(3)


目錄

  1. http協議是個什么東西
  2. http的請求類型都有哪些
  3. 常見的HTTP首部
  4. HTTP請求體
  5. HTTP響應體
  6. HTTP常見的響應狀態碼
  7. HTTP的cookieg管理

HTTP協議

HTTP是一種通用的網絡數據傳輸格式,它的傳輸內容不僅僅局限于HTML文件或者圖片,所有可以用字節序列表示的數據都可以使用HTTP進行傳輸。

HTTP通過TCP/IP進行數據傳輸,如果忽略底層的TCP協議的握手和揮手的細節,對于從客戶端到服務器的每一個請求和請求的響應,在HTTP1.0有下面幾個步驟:

  1. 默認情況下,客戶端在端口80開啟與服務器的一個TCP連接,當然也可以指定其他的端口。
  2. 客戶端向服務器發送消息,請求指定路徑上的資源。一個HTTP請求包括一個首部,可選項包括一個空行和這次請求的數據。
  3. 服務器向客戶端發送響應。響應以響應碼開頭,接著是包含元數據的首部,可選項包括一個空行以及所請求的文檔數據或者錯誤信息。
  4. 服務器關閉TPC連接。

在HTTP1.1(目前最常用的就是HTTP1.1)以及以后的HTTP版本中,可以通過一個TCP連接連續發送多個請求和接收多個響應。

也就是說,上面的1和4步驟中間的2和3步驟可以反復執行多次。另外,HTTP1.1中,請求數據和響應數據可以分塊發送,提高了擴展性。

HTTP請求方法

HTTP請求方法 描述 是否安全 是否冪等
GET 通常用于請求服務器獲取某個資源
HEAD 類似于GET,但是響應結果中不包含響應體,只包含協議信息和首部,通常用于測試資源是否存在或者是否被修改 -
POST 客戶端向服務器提交數據(支持HTML的表單數據),可能會導致新的資源的建立或者已有資源的修改
PUT 從客戶端向服務器傳送的數據取代指定的文檔的內容(全部取代)
PATCH 客戶端向服務器傳送的數據取代指定的文檔的內容(部分取代)
TRACE 回顯客戶端請求服務器的原始請求報文,用于"回環"診斷 -
OPTIONS 請求服務器獲取服務器支持的各種功能,可以詢問服務器支持什么類型的HTTP方法,一般用于性能測試 -
DELETE 請求服務器刪除指定的資源

安全 : 意味著使用該種HTTP請求方法不會發生任何數據的修改或者更新動作,也就是請求多次也不會影響到資源的狀態。

冪等 : 意味著使用該HTTP請求方法請求多次HTTP調用,無論調用多少次,請求結果或者資源的狀態是一樣的。

HTTP方法的安全性和冪等性是我們在設計HTTP接口時候需要重點考慮的兩個因素。

上面提到的POST和PUT方法的功能可以理解為相同的,兩者的主要區別在于POST不是冪等的,而PUT是冪等的。

在目前的Web開發中,POST方法已經被濫用,一般很少人會使用PUT,除非是推崇RESTFUL風格編程。

PUT方法和PATCH方法的功能類似,都是用客戶端請求的數據去替換掉服務器中指定文檔中的內容,不過PUT方法是全部替換,而PATCH方法是部分替換。

常見的HTTP首部

字段 首部類型 描述
User-Agent 請求 用戶代理,用于告知服務器當前客戶端使用的是什么瀏覽器
Host 請求 用于指定接收該請求的服務器的主機名和端口號
Accept-Charset 請求 告知服務器客戶端可以接收和處理哪些字符集
Accept-Encoding 請求 告知服務器客戶端可以接收和處理哪些編碼方式
Accept-Language 請求 告知服務器客戶端可以接收和處理哪些語言
Accept 請求 告知服務器客戶端可以接收和處理哪些媒體類型
Referer 請求 提供了包含當前請求的URL的文檔的URL
Cookie 請求 客戶端通過它向服務器傳送一個或者多個令牌,原則上Cookie并不是安全的首部,Cookie的內容也會緩存在客戶端。
Cache-Control 請求 告知服務器對當前的請求的響應結果進行緩存相關操作
Content-Type 通用 告知服務器或者客戶端當前請求或者響應結果的內容(媒體)類型
Content-Length 通用 告知服務器或者客戶端當前請求或者響應數據體的長度
Connection 請求 否需要持久連接,如果指定為Keep-Alive,可以提供持久連接
Origin 請求 指明當前的請求是一個針對跨域資源共享的請求
Access-Control-Allow-Origin 響應 表示服務器允許的該跨域資源共享的請求來源
Server 響應 用于告知客戶端服務器的相關信息
Set-Cookie 響應 Cookie對應,表示服務器設置成功的Cookie
Content-Encoding 響應 Accept-Encoding對應,用于服務器告知客戶端當前響應結果的內容編碼
Content-Language 響應 與Accept-Language對應,用于服務器告知客戶端當前響應結果的內容語言

其中 Accept的值可以是以下八種頂級的類型

text/* 表示人可讀的文字。
image/* 表示圖片。
model/* 表示3D模型,如VRML文件。
audio/* 表示音頻。
video/* 表示多媒體圖片、視頻,也可能是音頻。
application/* 表示二進制數據。
message/* 表示協議特定的信封,如Email消息和HTTP響應。
muitipart/* 表示多個文檔和資源的容器。

HTTP請求體

如果采用GET請求方法,只需要向遠處服務器提供URL,URL中的路徑和查詢字符串就可以匹配到需要查詢的資源。

但是URL中無法提供詳細的客戶端信息,像POST和PUT這些請求方法所攜帶的數據體有可能比較大。

因此HTTP需要請求體。HTTP請求體包括下面四個部分:

  • 一個起始請求行,包括HTTP方法、路徑、查詢字符串以及HTTP版本。
  • HTTP請求的首部。
  • 一個空行(兩個連續的回車或者換行對)。
  • 請求數據體。
GET /wp-admin/admin-ajax.php?postviews_id=23996&action=postviews&_=1538708851063 HTTP/1.1
Host: www.importnew.com
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Accept: */*
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.81 Safari/537.36
Referer: http://www.importnew.com/23996.html
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9

postviews_id=23996&action=postviews&_=1538708851063

HTTP響應體

響應體和請求體的格式類似,主要是返回服務器的響應數據到客戶端,包括服務器的一些信息和響應數據體。HTTP響應體主要包括下面的四個部分:

1、一個起始響應行,包括HTTP版本、狀態碼、狀態碼描述。

2、HTTP響應的首部。

3、一個空行(兩個連續的回車或者換行對)。

4、響應數據體。

HTTP/1.1 200 OK
Server: nginx
Date: Fri, 05 Oct 2018 03:07:37 GMT
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
Keep-Alive: timeout=2
Vary: Accept-Encoding
X-Powered-By: PHP/5.3.3
X-Robots-Tag: noindex
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
Content-Encoding: gzip

2995

Keep-Alive

在使用HTTP1.0的時候會為每個請求打開一個新的TCP連接,實際上,這導致了一個典型Web會話中打開和關閉所有連接所花費的事件遠遠大于實際傳輸數據所消耗的時間,特別是響應結果包含很多小文檔的會話。對于使用SSL或者TLS加密的HTTPS連接,這個問題更加嚴重,因為建立一個安全的Socket的握手過程遠比建立常規的Socket需要更多的工作。

在HTTP1.1和后面的版本中,服務器不必在返送響應之后就關閉連接。已經建立的連接可以保持打開,在同一個Socket上等待來自客戶端的新請求。簡單來說,就是可以在一個TCP連接上連續發送多個請求和連續進行多個請求的響應。

客戶端可以在HTTP請求首部中添加一個Connection請求頭,指定值為Keep-Alive,這樣就能實現Socket的重用:

Connection: Keep-Alive
HTTP1.1或者之后的版本,Keep-Alive是默認開啟的,不需要顯式指定,如果需要關閉可以設置為close:

Connection: close
一旦開啟了Keep-Alive,服務器在關閉一個Socket連接之前,如果有新的客戶端再次連接到服務器,那么就是重用Socket。在JDK中可以通過系統屬性來控制如果使用HTTP的Keep-Alive:

http.keepAlive:默認值為true,默認開啟HTTP的Keep-Alive。

http.maxConnections:同時保持打開的Socket數量的最大值,默認值為5。

http.keepAlive.remainingData:默認值為false,如果設置為true,則JDK在丟棄連接之后會完成剩余數據的清理。

sun.net.http.errorstream.enableBuffering:默認值為false,如果設置為true,則嘗試緩存400和500狀態碼的相對小的錯誤流,從而能釋放連接以備后續使用。

sun.net.http.errorstream.bufferSize:為緩存錯誤流的緩沖區的字節大小,默認值為4096字節,只有上一項為true的時候才有意義。

sun.net.http.errorstream.timeout:默認值為300ms,讀取錯誤流超時的毫秒數。

常見的HTTP狀態碼

簡單的說

  • 響應碼100-199表示一個提供信息的響應。
  • 響應碼200-299表示請求成功。
  • 響應碼300-399表示重定向。
  • 響應碼400-499表示一個客戶端引發的錯誤。
  • 響應碼500-599表示一個服務器引發的錯誤。
狀態碼 狀態碼消息 含義 HttpURLConnection中的常量 簡單描述
1xx - 信息狀態碼。 - 不常見,暫不考慮
100 Continue 服務器準備接受請求主體,客戶端發送請求主體;這允許客戶端在請求發送大量數據之前詢問服務器是否接受請求。 - 不常見,暫不考慮
101 Switching Protocols 服務器接受客戶端在Upgrade首部字段中要求改變應用的協議請求,如從HTTP轉換為WebSockets。 - 不常見,暫不考慮
2xx - 表示請求成功。 - -
200 OK 最常見的響應碼,代表請求成功。如果請求方法是GET或者POST,所請求的數據與正常的首部都包含在響應體中。如果請求方法是HEAD,則只包含首部信息。 HTTP_OK 處理請求成功
201 Created 服務器已經在響應體中指定的URL創建了對應的資源。客戶端現在應當嘗試加載該URL。這個響應碼只在響應POST請求時發送。 HTTP_CREATED 創建成功
202 Accepted 表示請求已經被處理,但是處理尚未結束,所以不會返回任何響應數據。 HTTP_ACCEPTED 接受請求
203 Non-Authoritative Information 由緩存代理或者其他本地源返回資源的表示,不能保證是最新的。 HTTP_NOT_AUTHORITATIVE 無權威的返回結果
204 No Content 服務器已經成功處理了該請求,但是沒有信息發回給客戶端。一般是由于服務器上的表單處理邏輯的問題,只接收數據不返回數據。 HTTP_NO_CONTENT 無返回內容
205 Reset Content 服務器已經成功處理了該請求,但是沒有信息發回給客戶端。客戶端應該清除發送請求的表單信息。 HTTP_RESET 重置內容
206 Partial Content 服務器返回客戶端請求的資源的部分內容,而不是整個文檔。 HTTP_PARTIAL 部分內容
3xx - 重定向。 - -
300 Multiple Choices 服務器為所請求的文檔提供一組不同的表示。 HTTP_MULT_CHOICE 多重選擇
301 Moved Permanently 資源已經移動到一個新的URL。客戶端應當自動加載這個URL的資源。 HTTP_MOVE_PERM 永久移動
302 Moved Temporarity 資源暫時移動到一個新的URL,但其位置在不久的將來還會再次改變。 HTTP_MOVE_TEMP 臨時移動
4xx - 客戶端錯誤 - -
400 Bad Request 客戶端向服務器發出的請求使用了不正確的語法。 HTTP_BAD_REQUEST 錯誤請求
401 Unauthorized 訪問這個URL需要身份驗證,一般是用戶名和口令。 HTTP_UNAUTHORIZED 未授權
403 Forbidden 服務器理解請求,但是有意拒絕進行處理。 HTTP_FORBIDDEN 禁止訪問
404 Not Found 最常見的錯誤響應,指示服務器找不到所請求的資源。 HTTP_NOT_FOUND 未找到資源
405 Method Not Allowed 請求方法不支持用于請求指定的資源。 HTTP_BAD_METHOD 方法禁用
406 Not Acceptable 所請求的資源不能以客戶端希望的格式提供,客戶端期望的格式由請求HTTP首部Accept字段指定。 HTTP_NOT_ACCEPTABLE 不接受
5xx - 服務端錯誤 - -
500 Internale Server Error 服務器內部異常。 HTTP_SERVER_ERROR 服務器異常
501 Not Implemented 服務器不具備完成請求的功能。 HTTP_NOT_IMPLEMENTED 尚未實現
502 Bad Gateway 服務器作為網關或代理,從上游服務器收到無效響應。 HTTP_BAD_GATEWAY 錯誤網關
503 Service Unavailable 服務器暫時無法處理請求,可能是超負荷或者維護等原因。 HTTP_UNAVAILABLE 服務不可用

Cookie和Cookie管理

一般在Servlet應用中,Cookie是識別當前用戶,實現持久會話的最佳方式。

從過期時間分類來看,Cookie分為會話Cookie和持久Cookie,會話Cookie的過期時間比較短,持久Cookie的過期時間比較長或者不會過期,Cookie的過期策略等控制應該由服務端控制。

由于Cookie是直接暴露在客戶端,一般不能使用Cookie存放敏感的數據,需要存放敏感數據可以考慮使用數據加密處理。

很多網站使用一些小文本串在連接之間存儲持久的客戶端狀態,這些小文本串稱為Cookie(中文翻譯為:小甜點)。

Cookie在請求和響應的首部從服務器傳到客戶端,再從客戶端傳回服務器,服務器使用Cookie來指示sessionID、購物車內容、登錄憑據等。

除了簡單的name=value對,Cookie可以有多個屬性來控制它們的作用域,包括過期日期、路徑、域、端口、版本和安全選項。

JDK中java.net.CookieStore類提供了對Cookie的增刪查操作,它的默認實現是java.net.InMemoryCookieStore,如果實現CookieStore,JDK中的Cookie默認是存放在內存中的。

另外,java.net.CookieManager內部持有CookiePolicy和CookieStore,定義了一系列管理Cookie的方法,一般通過CookieManager操作Cookie,當然也可以通過實現CookieStore,覆蓋默認的CookieManager來實現Cookie的自定義管理。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • http協議有http0.9,http1.0,http1.1和http2三個版本,但是現在瀏覽器使用的是htt...
    一現_閱讀 1,885評論 0 3
  • 6.1 公鑰密鑰加密原理 6.1.1 基礎知識 密鑰:一般就是一個字符串或數字,在加密或者解密時傳遞給加密/解密算...
    AndroidMaster閱讀 4,030評論 1 8
  • HTTP協議,全稱超文本傳輸協議(HyperText Transfer Protocol),是目前互聯網上應用最為...
    darrenW閱讀 625評論 0 0
  • 本文是《圖解HTTP》讀書筆記的第二篇,主要包括此書的第六章內容,因為第六章的內容較多,而且比較重要,所以單獨寫為...
    lijiankun24閱讀 1,391評論 0 6
  • 昨晚有朋友做分享課,因故沒去。群里收到如下作業: 今晚講的后半部分來源于《兒童愛之語》這本書,想...
    陳潔007閱讀 399評論 0 1