TCP包頭格式
- 剛開始,客戶端和服務端都處于CLOSED狀態,先是服務端主動監聽某個埠,處于LISTEN狀態,
- 客戶端主動發起SYN,之后處于SYN-SENT狀態
- 客戶端收到發起的連接,回傳SYN,并且ACK客戶端的SYN,之后處于SYN-RCVD狀態
- 客戶端收到服務端發送的SYN和ACK之后,發送ACK的ACK,之后處于ESTABLISHED狀態,因為它一發一收成功了,
- 服務端收到ACK的ACK之后,處于ESTABLISHED狀態,因為它也一發一收成功了,
- 斷開的時候,當A向B發送有個FIN,告訴B我要斷開,之后A處于FIN-WAIT-1狀態
- B收到A的FIN之后,發送給A FIN告訴A它知道了,然后B處于CLOSED-WAIT狀態
- A收到B發送的ACK之后,進進入FIN-WAIT-2狀態,如果這個時候B跑路,那么A將永遠處于在這個狀態里面,TCP協議里面并沒有對這個狀態的處理,但是Linux有,可以調整tcp_fin_timeout引數,設定一個超時時間
- 如果B沒有跑路,向A發送FIN到A時,A發送FIN的ACK到B,A結束FIN-WAIT-2的狀態,按說A可以直接跑路了,但是最后的這個ACK萬一B收不到呢?則B后重新發送一個FIN到A,這個時候A已經跑路的話,B就再也收不到ACK了,因而TCP協議要求A最后等待一段時間TIME_WAIT,這個時間要足夠長,長到如果B沒收到ACK的話,B的FIN會重新發送,A會重新發送一個ACK并且足夠時間到達B
- A直接跑路還有一個問題,A的埠就直接空出來了,但是B不知道,B原來發過的很多包很可能還在路上,如果A的埠被一個新的應用占用了,這個新的應用會受到上個連接中B發過來的包,雖然序列號是重新生成的,但是這里要上一個雙保險,防止產生混亂,因而也需要等足夠長的時間,等到原來B發送的所有的包都死翹翹,再空出埠來
- 等待時間設為2MSL,MSL是Maximum Segment Lifetime,報文最大生存空間,它是任何報文在網路上存在的最長時間,超過這個時間報文獎杯丟棄,因為TCP報文基于是IP協議的,而IP頭中有一個TTL域,是IP資料報可以經過的最大路由數,沒經過一個處理他的路由器此值就減1,當此值為0時則資料報將被丟棄,同事發送ICMP報文通知源主機,協議規定MSL為兩分鐘,實際應用中常用的是30秒,1分鐘,2分鐘
- 還有一種例外情況就是,B超過了2MSL的時間,依然沒有收到它發的FIN的ACK,按照TCP原理,B還會重發FIN,這個時候A再收到這個包之后,A就表示,我已經在這里等了這么久的時間了,之后的我都不認了,于是就直接發送RST,B就知道A早就跑了,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/112908.html
標籤:其他
