互聯網協議(Internet ProtocolSuite)是一個網絡通訊模型,以及一整個網絡傳輸協議家族,爲互聯網的基礎通訊架構。它常被通稱爲TCP/IP協議族(英語:TCP/IP Protocol Suite,或TCP/IP Protocols),簡稱TCP/IP。緩存
由上到下分別爲:應用層,傳輸層,網際層,網絡接入層服務器
層級 | 主要協議 |
---|---|
應用層 | HTTP、FTP、Telnet、DNS、SMTP |
傳輸層 | TCP、UDP |
網絡層 | IP、ICMP、IGMP |
網絡接入層 | ARP、RARP |
TCP(Transmission Control Protocol 傳輸控制協議)是一種面向鏈接的、可靠的、基於字節流的傳輸層通訊協議。網絡
標識數據從哪來發到哪去。架構
爲了解決亂序的問題,有了它就知道哪一個包先來,哪一個包後來。性能
發出去的包應該有確認,這樣才能保證消息的可靠性,就算沒收到也應該有個迴應,由於TCP做爲IP的上一層協議,是沒辦法保證網絡必定是穩定的,有可能丟包,TCP只能不斷重傳,直到送達,這樣能夠解決不丟包的問題。ui
例如:SYN表示發起鏈接,ACK表示回覆,FIN表示結束鏈接,RST表示鏈接重置,PSH表示有 DATA數據傳輸。網絡傳輸協議
SYN(synchronous創建聯機)spa
ACK(acknowledgement 確認)線程
PSH(push傳送)code
FIN(finish結束)
RST(reset重置)
URG(urgent緊急)
三次握手,其實就是創建TCP鏈接的一個過程,這個過程須要客戶端和服務端總共發送三個包來確認鏈接。
客戶端A和服務器B通信
A:我要和你鏈接。單相思是沒有用的,必需要B贊成。
B:好,我贊成你和我鏈接。這時候A不知道你贊成仍是不一樣意,因此得告訴A。
A:收到B贊成的消息,創建鏈接。A知道B贊成了就能夠直接創建鏈接了。
因此,創建TCP鏈接最少得發三個包,兩個少了,4個多了,不必。
客戶端A和服務器B進行通信
起初,客戶端A、服務器B處於CLOSE狀態。服務器B監聽某個端口,進入LISTEN狀態。
- 第一次握手:客戶端A發送狀態位SYN=1(A向B創建鏈接),隨機產生一個seq=x給服務器B表示發起鏈接,以後處於SYN-SENT狀態
- 第二次握手:服務器B接受到A的鏈接請求,再向A發送一個狀態位ACK=1(ACK客戶端的鏈接),SYN=1(B贊成和A鏈接),確認序號ack=x+1(就是收到A的包的序號seq+1),隨機產生一個序號seq=y。以後進入SYN-RCVD 狀態。
- 第三次握手:客戶端A收到B的確認,檢查ack是否爲x+1,以及ACK是否爲1,若正確,發送順序號ack=y+1,ACK=1(ACK服務器的鏈接)的包給B,告訴B我已經知道你贊成和我鏈接了,以後客戶端A進入ESTABLISHED狀態,服務器B收到後確認seq值與ACK=1則鏈接創建成功。一樣進入ESTABLISHED狀態。
如圖:
SYN攻擊: 在三次握手過程當中,Server發送SYN-ACK以後,收到Client的ACK以前的TCP鏈接稱爲半鏈接(half-open connect),此時Server處於SYN_RCVD狀態,當收到ACK後,Server轉入ESTABLISHED狀態。SYN攻擊就是Client在短期內僞造大量不存在的IP地址,並向Server不斷地發送SYN包,Server回覆確認包,並等待Client的確認,因爲源地址是不存在的,所以,Server須要不斷重發直至超時,這些僞造的SYN包將產時間佔用未鏈接隊列,致使正常的SYN請求由於隊列滿而被丟棄,從而引發網絡堵塞甚至系統癱瘓。SYN攻擊時一種典型的DDOS攻擊,檢測SYN攻擊的方式很是簡單,即當Server上有大量半鏈接狀態且源IP地址是隨機的,則能夠判定遭到SYN攻擊了,使用以下命令可讓之現行: #netstat -nap | grep SYN_RECV
四次揮手(Four-Way Wavehand)即終止TCP鏈接,就是指斷開一個TCP鏈接時,須要客戶端和服務端總共發送4個包以確認鏈接的斷開。
假如,上面的客戶端A要和服務器B要斷開鏈接了,A不玩了,此時A和B都處於ESTABLISHED狀態
第一次揮手:A和B說,我不玩了,給B發送一個FIN(結束鏈接)。A由ESTABLISHED變爲FIN-WAIT-1狀態。
第二次揮手:B收到A說不玩了的請求,因而對A說,我知道了。而後B由EStABLISHED狀態進入CLOSED-WAIT狀態,可是B這可能還有A上次請求的包還沒發完,因此A收到B的ACK後由FIN-WAIT-1狀態進入到FIN-WAIT-2狀態。
第三次揮手:B已經處理完了全部要發給A的包,能夠結束鏈接了,因而向A發送一個FIN,B而後進入LAST-ACK狀態。
第四次揮手:A收到B的FIN請求,知道B能夠斷開鏈接了,接着向B發送一個ACK,而後A進入TIME-WAIT狀態,等待2MSL(Maximun Segment LifeTime:最大報文生存時間)。B收到A的ACK後就進入到CLOSED狀態,A等待2MSL也進入到CLOSED狀態。
如圖:
爲何最後A要等待2MSL呢?
複製代碼
一、由於A在收到B的FIN後給B發送了一個ACK,有可能B並無收到A的ACK,因此B會向A從新發送一個FIN請求,因此A要保證就算B沒收到我發送的ACK,A還能在接收到B的重發的FIN。A會重發一個ACK而且足夠時間到達B。
二、若是A直接跑路,A的端口就直接空出來了,可是B不知道啊,B原來向A發過的包頗有可能還在路上,若是A的端口被一個新應用佔用,那麼這個新應用會接受到上個鏈接中B發過來的包,雖然序列號是從新生成的,可是這裏爲了保險起見,A仍是得等待一個足夠長的時間,等這些包都死翹翹,在空出端口來。
首先,對於TCP通訊來講,每一個TCP Socket的內核中都有一個發送緩衝區和一個接收緩衝區,TCP的全雙工的工做模式及TCP的滑動窗口就是依賴於這兩個獨立的Buffer和該Buffer的填充狀態。 接收緩衝區把數據緩存到內核,若應用進程一直沒有調用Socket的read方法進行讀取,那麼該數據會一直被緩存在接收緩衝區內。無論進程是否讀取Socket,對端發來的數據都會通過內核接收並緩存到Socket的內核接收緩衝區。 read索要作的工做,就是把內核接收緩衝區中的數據複製到應用層用戶的Buffer裏。
進程調用Socket的send發送數據的時候,通常狀況下是講數據從應用層用戶的Buffer裏複製到Socket的內核發送緩衝區,而後send就會在上層返回。換句話說,send返回時,數據不必定會被髮送到對端。
明白了Socket讀寫數據的底層原理,咱們就很容易理解「阻塞模式」:對於讀取Socket數據的過程而言,若是接收緩衝區爲空,則調用Socket的read方法的線程會阻塞,直到有數據進入接收緩衝區;而對於寫數據到Socket中的線程來講,若是待發送的數據長度大於發送緩衝區空餘長度,則會阻塞在write方法上,等待發送緩衝區的報文被髮送到網絡上,而後繼續發送下一段數據,循環上述過程直到數據都被寫入到發送緩衝區爲止
從前面分析的過程來看,傳統的Socket阻塞模式直接致使每一個Socket都必須綁定一個線程來操做數據,參與通訊的任意一方若是處理數據的速度較慢,會直接拖累到另外一方,致使另外一方的線程不得不浪費大量的時間在I/O等待上,因此這就是Socket阻塞模式的「缺陷」。可是這種模式在少許的TCP鏈接通訊的狀況下,雙方均可以快速的傳輸數據,這個時候的性能是最高的。