資訊科普系列(17)-網路封包結構
TCP (Transmission Control Protocol)
TCP是一個面向連結(connection-oriented)、可靠的(reliable)、位元流式(byte stream)的傳輸協議。其使用三方交握來建立可靠的連接。TCP可以重新排序到達順序錯誤的分段,並重新傳送遺失的分段。
在 TCP 連接建立過程中,雙方通常會協商最大分段大小(MSS),這代表每個 TCP 資料段中可攜帶的最大位元數。MSS 的大小通常受到底層網路的MTU(Maximum Transmission Unit)限制,確保 TCP 資料段在傳輸過程中不需要分片,從而提高效率。
TCP Maximum Segment Size (MSS)
MSS 是網路裝置可以接收的最大 TCP 區段大小。MSS 以 bytes 為單位。
MTU -(TCP header+ IP header)= MSS
MSS 預設為 1,460 個位元組,因為MTU 為 1,500 bytes 而 TCP header 與 IP header 最大為20 bytes 。
封包欄位
TCP Header
- 來源 Port(16 bits): 來源/應用程式 的 port 號
- 目的地 Port (16 bits): 應用程式的 port 號,有助於將資料發送到適當的應用程式。
- 序列號 (32 bits): 標示了TCP封包中第一个byte在對應方向的傳輸中對應的序號
- 確認號(32 bits): 用來通知發送端已經成功接收到資料。
- 資料偏移(4 bits): 包含TCP header 大小,與告知資料從哪裏開始
- 控制標記 (9 bits): TCP使用一些控制標記來調節連線。一些重要的標誌包括:SYN:建立一個連結、ACK:確認接收到的資料、FIN:結束一個連結、RST(重置):發生錯誤時重置連接。
- 窗口大小 (16 bits): 接收方通知發送方它目前能夠接收多少字節的資料,而不需要等待確認。用於TCP的流量控制。
- 檢驗和 (16 bits): 用來檢查 header 或 data 是否受損。
- 緊急指針 (16 bits): 控制標記URG才會啟動,允許在正常資料流中插入一些具有高優先級的訊息。
- Options: 長度不定,但長度必須以是32bits的整數倍。常見的選項包括MSS、SACK、Timestamp等等。
三方交握
- client 向 server 發出連接請求的封包,其 header 中的帶有 SYN = 1,初始序列號 seq = m,說明傳送封包時的第一個位元序號是 m。
- server 收到SYN封包後,回覆封包會帶有SYN =1 與ACK = 1 ,而確認號ack會等於m+1,自己選擇的序號 seq = n 。
- client 收到此封包後向 server 給出確認 ACK =1,還會帶有ack = n + 1
- 雙方都會在收到確認通知其上層應用程式 TCP 連接已經建立,之後就會進入連線狀態開始交換資料。
一般來說上面用來建立連接的初始序列號ISN(即m和n)的值是隨機選取的。RFC1948提出了一個ISN隨機生成的演算法
ISN = M + F(localhost, localport, remotehost, remoteport)
其中M是一个計時器,每隔4毫秒加1。F是一个Hash演算法,根據來源IP、目的地IP、來源 port、目的地 port 生成一个隨機數。
四次揮手
- client 關閉TCP連接時, 連接釋放封包的標記位 會帶有 FIN = 1,ACK=1,其序號seq = x,確認號ack=y,等待 server 確認。
- server 收到 client 的FIN封包後,發出確認,確認號 ack = x + 1,而這個封包的序列號 seq = y。
- 當 client 收到 server 的ACK確認封包後,A進入FIN_WAIT_2狀態 。
若 server 已經沒有要向 client 發送的數據,其應用程式就通知 TCP 釋放連接。server 傳送連接釋放封包,FIN=1,ACK=1,封包序列號 seq= z,確認號ack=x+1。 - A 收到連接釋放封包後,必須發出確認,在確認封包中 ACK = 1,確認號 ack = z + 1,自己的序號 seq = x + 1。 client 經過2MSL時間後就進入關閉狀態,在 server 接收到 client 的確認封包後,立即進入關閉狀態。兩者都進入關閉狀態後整個TCP連接釋放。
MSL ( Maximum Segment Lifetime ),是指封包在網路上存在的的最長時間,超過這個時間封包將被丟棄。RFC793定義了MSL為2分鐘,Linux設定成了30s。
HTTP ( HyperText Transfer Protocol )
是一種用於分佈式、協作式和超媒體訊息系統的應用層協定。由 client 發送 HTTP Request 到 server,然後 server 返回 HTTP Response 。
HTTP-message = Request | Response
HTTP-message 會包含以下內容:
- URL 和參數
- 一個 HTTP method
- HTTP header
- Message Body
HTTP method
表示 HTTP request 期待伺服器執行的動作。
- GET:向指定的資源發出請求。
- POST:向指定資源提交資料,可在Body中帶資料。
- PUT:取代指定的資源。
- DELETE:刪除指定的資源。
- HEAD:與GET相似,但只會取得 header 與HTTP status。
- CONNECT:通常用在Proxy。
- OPTIONS:回傳這個伺服器支援的所有 HTTP Method。
- TRACE:回傳收到的請求內容。
header 欄位
header 欄位根據用途被分為以下類型:
- General Header Fields-在請求訊息和回應訊息都適用的欄位
- Request Header Fields-允許 client 傳遞有關請求以及有關 client 自身附加訊息給 server。
- Response Header Fields-允許 server 傳遞有關回應的額外訊息,這些訊息無法放在 Status-Line 中。這些 header 字段提供有關 server 以及Request-URI 資源的訊息。
- Entity Header Fields-請求和回應訊息在不受 request method 或 status code 限制的情況下,可能傳輸一個實體。一個實體包括實體 Header 和實體主體。
Request
在 client 發送到 server 的 request message 的第一行中,會有應用於該資源的方法、資源的識別碼,以及使用的協定版本。
Request-Line = Method SP Request-URI SP HTTP-Version
Request-URI = "*" | absoluteURI | abs_path | authority
ex.
- OPTIONS * HTTP/1.1
- GET http://www.w3.org/pub/WWW/TheProject.html HTTP/1.1
- GET /pub/WWW/TheProject.html HTTP/1.1 Host: www.w3.org
必須使用以下規則來確定對 HTTP/1.1 request 所請求的資源
- 如果 Request-URI 是 absoluteURI,則 HOST 是 Request-URI 的一部分。在 request 中的任何 Host header field 必須被忽略。
- 如果 Request-URI 不是 absoluteURI,並且請求包括 Host header field,則HOST 由Host header field 決定。
- 如果由規則1或2確定的 HOST 在 server 上不是有效的主機,則回應必須是400(Bad Request)。
Response
在接收並解釋 request 後,server 會回覆一個 response。
response-message 的第一行是Status-Line,包括協定版本,後面是狀態碼及其相應的敘述。
Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase
Status-Code
是試圖理解並滿足 request 的3位數號碼,Reason-Phrase旨在提供Status-Code的簡短文字描述。
- 1xx: 資訊回應 - 請求已收到,正在處理
- 2xx: 成功回應 - 該操作已成功接收、理解並接受
- 3xx: 重定向 - 需要進一步採取行動以完成 request
- 4xx: Client Error - request 包含不良的語法或無法滿足
- 5xx: Server Error - server 未能滿足一個明顯有效的 request
封包傳遞
client 與 server 進行通信時,過程如下:
- 域名解析: client 會透過 DNS ,將對方的 Domain 解析為 IP 。
- ARP 解析: client 使用目標 IP 查詢本地的 ARP table,獲取對應的MAC。如果找不到,則需要進行ARP解析,發送ARP請求到網路以獲取目標的MAC。
- 資料傳輸: 在開始通信之前,client 和 server 會透過三方交握建立一個通信連接。一旦連接建立,資料就可以在 client 和 server 之間傳輸。
在兩個設備中傳輸的封包會帶上接收端 router 的 MAC 在讓我們可以傳封包過去,再透過 router 解析出來的 IP 將封包丟到指定的位置,在指定的位置組合TCP封包,再將資料傳給應用程式。
參考資料
https://www.cloudflare.com/zh-tw/learning/network-layer/what-is-mss/