一、TCP報文格式
下面是TCP報文格式圖:
(1) 序號, Seq(Sequence number), 占32位,用來標識從TCP源端向目的端發送的字節流,發起方發送數據時對此進行標記。
(2) 確認號, Ack(Acknowledge number), 占32位, 只有ACK標志位為1時,確認序號字段才有效,Ack=Seq+1。
(3) 標志位 有6種標示(SYN、ACK、PSH、RST、URG、FIN):
① SYN(synchronous建立聯機)
② ACK(acknowledgement 確認)
③ PSH(push傳送)
④ RST(reset重置)
⑤ URG(urgent緊急)
⑥ FIN(finish結束)
注:
① 不要將確認號Ack(Acknowledge number) 和 標志位中的 ACK(acknowledgement)混淆
二、三次握手
(1) 第一次握手: Client將標志位SYN置為1, 隨機產生一個seq=J, 並將該數據包發送給Server, Client進入SYN_SENT狀態, 等待
Server確認.
(2) 第二次握手: Server收到數據包后由標志位SYN=1知道Client請求建立連接, Server將標志位SYN和ACK都置為1,ack=J+1,
隨機產生一個值seq=K,並將該數據包發送給Client以確認連接請求,Server進入SYN_RECV狀態.
(3) 第三次握手: Client收到確認后, 檢查ack是否為J+1, ACK是否為1, 如果正確則將標志位ACK置為1,ack=K+1, 並將該數據
包發送給Server,Server檢查ack是否為K+1, ACK是否為1, 如果正確則連接建立成功, Client和Server進入
ESTABLISHED狀態, 完成三次握手, 隨后Client與Server之間可以開始傳輸數據了.
SYN攻擊:
在三次握手過程中, Server發送SYN_ACK之后, 收到Client的ACK之前的TCP連接稱為 半連接(half-open connect), 此時
Server處於SYN_RECV狀態,Server轉入ESTABLISHED狀態. SYN攻擊就是Client在短時間內偽造不存在的IP地址, 並向Server
不斷的發送SYN包, Server回復確認包, 並等待Client確認, 由於源地址不存在的, 因此Server需要不斷重發直至超時, 這些偽造的
SYN包將產時間占用未連接隊列, 導致正常的SYN請求因為隊列滿而被丟棄, 從而引起網絡堵塞甚至系統癱瘓. SYN攻擊時一種典
型的DDOS攻擊, 檢測SYN攻擊的方式非常簡單, 即當Server上有大量半連接狀態切源IP地址是隨機的, 則可以斷定遭到SYN攻擊
了, 使用如下命令可以讓之現行:
#netstat -nap | grep SYN_RECV
四、四次揮手
所謂四次揮手就是終止TCP連接, 就是要斷開一個TCP連接時, 需要客戶端和服務器總共進行四次交互。在socket編程中, 這個
執行過程由客戶端或者服務器任意一方執行close來觸發, 下面是斷開流程圖:
由於TCP連接時全雙工的, 因此, 每個方向都必須要單獨進行關閉, 這一原則是當一方完成數據發送任務后, 發送一個FIN來終止
這一方向的連接,收到一個FIN只是意味着這一方向上沒有數據流動了, 即不會再收到數據了, 但是在這個TCP連接上仍然能夠發送數
據,直到這一方向也發送了FIN. 首先進行關閉的一方將執行主動關閉,而另一方則執行被動關閉,上圖描述的即是如此。
(1) 第一次揮手: Client發送一個FIN, 用來關閉Client 到 Server的數據傳輸, Client進入FIN_WAIT_1狀態
(2) 第二次揮手: Server收到FIN后, 發送一個ACK給Client, 確認序號為收到的序號+1(與SYN相同, 一個FIN占用一個序號),
Server進入CLOSE_WAIT狀態
(3) 第三次揮手: Server發送一個FIN后, 用來關閉Server到Client的數據傳輸, Server進入LAST_ACK狀態
(4) 第四次揮手: Client收到FIN后, Client進入TIME_WAIT狀態, 接着發送一個ACK給Server, 確認序號為收到序號+1, Server
進入CLOSED狀態, 完成四次揮手
四、狀態
SYN_SENT狀態:
當客戶端SOCKET執行CONNECT連接時,它首先發送SYN報文,因此也隨即它會進入到了SYN_SENT狀態,並等待服務
端的發送三次握手中的第2個報文。SYN_SENT狀態表示客戶端已發送SYN報文. (發送端)
SYN_RCVD狀態: 這個狀態與SYN_SENT相呼應這個狀態表示接受到了SYN報文.
ESTABLISHED: 表示連接已經建立了.
CLOSE_WAIT狀態:
發起TCP連接關閉的一方稱為client,被動關閉的一方稱為server. 被動關閉的server收到FIN后, 但未發出ACK的TCP狀態
是CLOSE_WAIT. 出現這種狀況一般都是由於server端代碼的問題, 如果你的服務器上出現大量CLOSE_WAIT, 應該要考慮檢查代碼.
TIME_WAIT狀態:
表示收到了對方的FIN報文, 並發送出ACK報文, 就等2MSL后即可回到CLOSED可用狀態.
LAST_ACK:
表示被關閉的一方在發送FIN報文后, 最后等待對方的ACK報文. 當收到ACK報文后, 也即可以進入到CLOSED狀態了.
CLOSED: 表示連接中斷.
五、總結
關於三次握手與四次揮手通常都會有典型的面試題:
(1) 三次握手是什么或者流程? 四次握手呢? 答案前面分析就是.
(2) 為什么連接時是三次握手, 而關閉連接卻是四次揮手?
這是因為服務端在LISTEN狀態下, 收到建立連接請求的SYN報文后, 把ACK和SYN放在一個報文里發送給客戶端. 而關閉連接時,
當收到對方的FIN報文時, 僅僅表示對方不在發送數據了, 但是還能接收數據, 己方也未必全部數據都發送對方了, 所以己方可以立即
close, 也可以發送一些數據給對方后, 再發送FIN報文給對方來表示同意現在關閉連接, 因此, 己方ACK和FIN一般都會分開發送。
參考文章:
http://blog.csdn.net/xifeijian/article/details/12777187
http://www.cnblogs.com/Jessy/p/3535612.html
http://blog.csdn.net/renzhenhuai/article/details/12105457
http://www.cnblogs.com/jiangson/p/5980681.html