TCP有6種標示:SYN(創建聯機) ACK(確認) PSH(傳送) FIN(結束) RST(重置) URG(緊急) html
1、TCP三次握手
第一次握手服務器
客戶端向服務器發出鏈接請求報文,這時報文首部中的同部位SYN=1,同時隨機生成初始序列號 seq=x,此時,TCP客戶端進程進入了 SYN-SENT(同步已發送狀態)狀cookie
態。TCP規定,SYN報文段(SYN=1的報文段)不能攜帶數據,但須要消耗掉一個序號。這個三次握手中的開始。表示客戶端想要和服務端創建鏈接。網絡
第二次握手tcp
TCP服務器收到請求報文後,若是贊成鏈接,則發出確認報文。確認報文中應該 ACK=1,SYN=1,確認號是ack=x+1,同時也要爲本身隨機初始化一個序列號 seq=y,此post
時,TCP服務器進程進入了SYN-RCVD(同步收到)狀態。這個報文也不能攜帶數據,可是一樣要消耗一個序號。這個報文帶有SYN(創建鏈接)和ACK(確認)標誌,詢問客戶端url
是否準備好。設計
第三次握手server
TCP客戶進程收到確認後,還要向服務器給出確認。確認報文的ACK=1,ack=y+1,此時,TCP鏈接創建,客戶端進入ESTABLISHED(已創建鏈接)狀態。htm
TCP規定,ACK報文段能夠攜帶數據,可是若是不攜帶數據則不消耗序號。這裏客戶端表示我已經準備好。
思考:爲何要三次握手呢,有人說兩次握手就行了
舉例:已失效的鏈接請求報文段。
client發送了第一個鏈接的請求報文,可是因爲網絡很差,這個請求沒有當即到達服務端,而是在某個網絡節點中滯留了,直到某個時間纔到達server,原本這已是一個失效
的報文,可是server端接收到這個請求報文後,仍是會想client發出確認的報文,表示贊成鏈接。假如不採用三次握手,那麼只要server發出確認,新的創建就鏈接了,但其實這個
請求是失效的請求,client是不會理睬server的確認信息,也不會向服務端發送確認的請求,可是server認爲新的鏈接已經創建起來了,並一直等待client發來數據,這樣,server的
不少資源就沒白白浪費掉了,採用三次握手就是爲了防止這種狀況的發生,server會由於收不到確認的報文,就知道client並無創建鏈接。這就是三次握手的做用。
2、TCP數據的傳輸過程
創建鏈接後,兩臺主機就能夠相互傳輸數據了。以下圖所示:
1)主機A初始seq爲1200,滑動窗體爲100,向主機B傳遞數據的過程。
2)假設主機B在徹底成功接收數據的基礎上,那麼主機B爲了確認這一點,向主機A發送 ACK 包,並將 Ack 號設置爲 1301。所以按以下的公式確認 Ack 號:
Ack號 = Seq號 + 傳遞的字節數 + 1 (這是在徹底接受成功的狀況下)
3)主機A得到B傳來的ack(1301)後,開始發送seq爲1301,滑動窗體爲100的數據。
......
與三次握手協議相同,最後加 1 是爲了告訴對方要傳遞的 Seq 號。上面說了,主機B徹底成功接收A發來的數據纔是這樣的,若是存在丟包該如何。
下面分析傳輸過程當中數據包丟失的狀況,以下圖所示:
上圖表示經過 Seq 1301 數據包向主機B傳遞100字節的數據,但中間發生了錯誤,主機B未收到。通過一段時間後,主機A仍未收到對於 Seq 1301 的ACK確認,所以嘗試
重傳數據。爲了完成數據包的重傳,TCP套接字每次發送數據包時都會啓動定時器,若是在必定時間內沒有收到目標機器傳回的 ACK 包,那麼定時器超時,數據包會重傳。
上面也只是一種可能,好比數據1250丟失,那麼Ack返回的就是1250,具體的能夠詳細看下博客:【TCP協議】(1)---TCP協議詳解,這裏面滑動窗口有說明。
3、TCP的四次揮手
第一次揮手
TCP發送一個FIN(結束),用來關閉客戶到服務端的鏈接。
客戶端進程發出鏈接釋放報文,而且中止發送數據。釋放數據報文首部,FIN=1,其序列號爲seq=u(等於前面已經傳送過來的數據的最後一個字節的序號加1),
此時,客戶端進入FIN-WAIT-1(終止等待1)狀態。 TCP規定,FIN報文段即便不攜帶數據,也要消耗一個序號。
揮手
服務端收到這個FIN,他發回一個ACK(確認),確認收到序號爲收到序號+1,和SYN同樣,一個FIN將佔用一個序號。
服務器收到鏈接釋放報文,發出確認報文,ACK=1,ack=u+1,而且帶上本身的序列號seq=v,此時,服務端就進入了CLOSE-WAIT(關閉等待)狀態。TCP服務器
通知高層的應用進程,客戶端向服務器的方向就釋放了,這時候處於半關閉狀態,即客戶端已經沒有數據要發送了,可是服務器若發送數據,客戶端依然要接受。這個
狀態還要持續一段時間,也就是整個CLOSE-WAIT狀態持續的時間。
客戶端收到服務器的確認請求後,此時,客戶端就進入FIN-WAIT-2(終止等待2)狀態,等待服務器發送鏈接釋放報文(在這以前還須要接受服務器發送的最後的數據)。
揮手
服務端發送一個FIN(結束)到客戶端,服務端關閉客戶端的鏈接。
服務器將最後的數據發送完畢後,就向客戶端發送鏈接釋放報文,FIN=1,ack=u+1,因爲在半關閉狀態,服務器極可能又發送了一些數據,假定此時的序列號爲seq=w,
此時,服務器就進入了LAST-ACK(最後確認)狀態,等待客戶端的確認。
揮手
客戶端發送ACK(確認)報文確認,並將確認的序號+1,這樣關閉完成。
客戶端收到服務器的鏈接釋放報文後,必須發出確認,ACK=1,ack=w+1,而本身的序列號是seq=u+1,此時,客戶端就進入了TIME-WAIT(時間等待)狀態。注意此時
TCP鏈接尚未釋放,必須通過2∗∗MSL(最長報文段壽命)的時間後,當客戶端撤銷相應的TCB後,才進入CLOSED狀態。
服務器只要收到了客戶端發出的確認,當即進入CLOSED狀態。一樣,撤銷TCB後,就結束了此次的TCP鏈接。能夠看到,服務器結束TCP鏈接的時間要比客戶端早一些。
思考:那麼爲何是4次揮手呢?
爲了確保數據可以完成傳輸。
關閉鏈接時,當收到對方的FIN報文通知時,它僅僅表示對方沒有數據發送給你了;但未必你全部的數據都所有發送給對方了,因此你能夠未必會立刻會關閉SOCKET,也
即你可能還須要發送一些數據給對方以後,再發送FIN報文給對方來表示你贊成如今能夠關閉鏈接了,因此它這裏的ACK報文和FIN報文多數狀況下都是分開發送的。
可能有人會有疑問,tcp我握手的時候爲什麼ACK(確認)和SYN(創建鏈接)是一塊兒發送。揮手的時候爲何是分開的時候發送呢.
由於當Server端收到Client端的SYN鏈接請求報文後,能夠直接發送SYN+ACK報文。其中ACK報文是用來應答的,SYN報文是用來同步的。可是關閉鏈接時,當Server端收到
FIN報文時,極可能並不會當即關閉 SOCKET,因此只能先回復一個ACK報文,告訴Client端,"你發的FIN報文我收到了"。只有等到我Server端全部的報文都發送完了,我才能
發送FIN報文,所以不能一塊兒發送。故須要四步揮手。
思考:客戶端忽然掛掉了怎麼辦?
正常鏈接時,客戶端忽然掛掉了,若是沒有措施處理這種狀況,那麼就會出現客戶端和服務器端出現長時期的空閒。解決辦法是在服務器端設置保活計時器,每當服務器收到
客戶端的消息,就將計時器復位。超時時間一般設置爲2小時。若服務器超過2小時沒收到客戶的信息,他就發送探測報文段。若發送了10個探測報文段,每個相隔75秒,
尚未響應就認爲客戶端出了故障,於是終止該鏈接。
4、SYN(洪水)攻擊
背景
初始化鏈接的 SYN 超時問題Client發送SYN包給Server後掛了,Server回給Client的SYN-ACK一直沒收到Client的ACK確認,這個時候這個鏈接既沒創建起來,也不能算
失敗。這就須要一個超時時間讓Server將這個鏈接斷開,不然這個鏈接就會一直佔用Server的SYN鏈接隊列中的一個位置,大量這樣的鏈接就會將Server的SYN鏈接隊列耗盡,
讓正常的鏈接沒法獲得處理。
目前,Linux下默認會進行5次重發SYN-ACK包,重試的間隔時間從1s開始,下次的重試間隔時間是前一次的雙倍,5次的重試時間間隔爲1s, 2s, 4s, 8s, 16s,總共31s,第
5次發出後還要等32s都知道第5次也超時了,因此,總共須要 1s + 2s + 4s+ 8s+ 16s + 32s = 63s,TCP纔會把斷開這個鏈接。因爲,SYN超時須要63秒,那麼就給攻擊者一
個攻擊服務器的機會,攻擊者在短期內發送大量的SYN包給Server(俗稱SYN flood攻擊),用於耗盡Server的SYN隊列。
什麼是 SYN 攻擊
SYN 攻擊指的是,攻擊客戶端在短期內僞造大量不存在的IP地址,向服務器不斷地發送SYN包,服務器回覆確認包,並等待客戶的確認。因爲源地址是不存在的,服務器
須要不斷的重發直至超時,這些僞造的SYN包將長時間佔用未鏈接隊列,正常的SYN請求被丟棄,致使目標系統運行緩慢,嚴重者會引發網絡堵塞甚至系統癱瘓。SYN 攻擊是一
種典型的 DoS攻擊。
如何檢測 SYN 攻擊?
檢測 SYN 攻擊很是的方便,當你在服務器上看到大量的半鏈接狀態時,特別是源IP地址是隨機的,基本上能夠判定這是一次SYN攻擊。在 Linux/Unix 上可使用系統自帶的
netstats 命令來檢測 SYN 攻擊。
如何防護 SYN 攻擊?
SYN攻擊不能徹底被阻止,除非將TCP協議從新設計。咱們所作的是儘量的減輕SYN攻擊的危害,常見的防護 SYN 攻擊的方法有以下幾種:
縮短超時(SYN Timeout)
時間增長最大半鏈接數
過濾網關防禦SYN
cookies技術
4、TCP和UDP的區別
我這裏簡單列舉幾個,由於我尚未研究UDP這個協議。
一、基於鏈接與無鏈接;UDP是無鏈接的,即發送數據以前不須要創建鏈接
二、TCP保證數據正確性,UDP可能丟包,TCP保證數據順序,UDP不保證。也就是說,經過TCP鏈接傳送的數據,無差錯,不丟失,不重複,且按序到達;UDP盡最大努力交付
,即不保證可靠交付Tcp經過校驗和,重傳控制,序號標識,滑動窗口、確認應答實現可靠傳輸。如丟包時的重發控制,還能夠對次序亂掉的分包進行順序控制。
三、UDP具備較好的實時性,工做效率比TCP高,適用於對高速傳輸和實時性有較高的通訊或廣播通訊。
四、每一條TCP鏈接只能是點到點的;UDP支持一對一,一對多,多對一和多對多的交互通訊。
五、TCP對系統資源要求較多,UDP對系統資源要求較少。