TCP三次握手、四次斷開與十一種狀態

一:OSI 模型 Open System Interconnect開放系統互連參考模型,是由ISO(國際標準化組織)定義的,它是個靈活的、穩健的和可互操做的模型,OSI模型的目的是爲了規範不一樣系統的互聯標準,使兩個不一樣的系統可以較容易的通訊,而不須要改變底層的硬件或軟件的邏輯,OSI模型分爲七層,OSI把網絡按照層次分爲七層,由下到上分別爲物理層、數據鏈路層、網絡層、傳輸層、會話層、表示層、應用層。

1.1:第七層:應用層的功能:
爲應用軟件提供接口,使應用程序可以使用網絡服務。常見的應用層協議:
http(80)、ftp(20/21)、smtp(25)、pop3(110)、telnet(23)、dns(53)等
1.2:第六層:表示層的功能:
數據的編碼和解碼、數據的加密和解密、數據和壓縮和解壓縮,常見的標準有JPEG/ASCII等
1.3:第五層:會話層的功能:
創建、管理和終止表示層實體之間的會話鏈接,在設各或節點之間提供會話控制,它在系統之間協調通訊過程,並提供3種不一樣的方式來組織它們之間的通訊:單工、半雙工和全雙工
1.4:第四層:傳輸層的功能:
負責創建端到端的鏈接,保證報文在端到端之間的傳輸。提供可靠TCP及不可靠UDP的傳輸機制,服務點編址、分段與重組、鏈接控制、流量控制、差錯控制。
1.5:第三層:網絡層的功能:
定義邏輯地址,邏輯尋址,將數據分組從源傳輸到目的,路徑選擇、路由發現、維護路由表,功能是隔離廣播域;隔離廣播,路由選擇;維護路由表,尋址及轉發,流量管理並鏈接廣域網
1.6:第二層:數據鏈路層的功能:
組幀、物理編址,將數據幀從鏈路上的一個節點傳遞到另外一個節點,流量控制、差錯控制、接入控制
1.7:第一層:物理層的功能:
在介質上傳遞比特流,定義接口和媒體的物理特性,定義比特的表示、數據傳輸速率、信號的傳輸模式(單工、半雙工、全雙工),定義網絡物理拓撲(網狀、星型、環型、總線型等)linux

二:TCP 協議簡介:

TCP,全稱Transfer Control Protocol,中文名爲傳輸控制協議,它工做在OSI的傳輸層,提供面向鏈接的可靠傳輸服務,TCP的工做主要是創建鏈接,而後從應用層程序中接收數據並進行傳輸。TCP採用虛電路鏈接方式進行工做,在發送數據前它須要在發送方和接收方創建一個鏈接,數據在發送出去後,發送方會等待接收方給出一個確認性的應答,不然發送方將認爲此數據丟失,並從新發送此數據。apache

三:TCP三次握手:

在創建鏈接的時候,所謂的客戶端與服務端是相對應的,即要看是誰主動鏈接的誰,若是A主動鏈接B那麼A就是客戶端而B是服務端,若是返過來B主動鏈接A,那麼B就是客戶端而A就成了服務端。
3.1:鏈接過程:
第一次握手:客戶端發送SYN標誌位爲1的請求到服務端,並隨機生成一個seq 序列號x,其中seq是隨機產生的數據包的序列號。
第二次握手:服務器收到客戶端請求並返回SYN=1,ACK=1,seq=y,ack=x+1,其中ACK=1表示是響應報文,seq=y是服務器隨機產生的數據包序列號,ack=x+1是確認客戶端序列號有效並返回給客戶端確認。
第三次握手:客戶端收到服務器的確認ack=x+1有效的驗證信息,即在本身發送的序列號基礎之上加了1表示服務器收到並返回,表示第二次鏈接有效,而後客戶端恢回覆ACK=1,seq=x+1,ack=y+1,這是講服務器發來+1後的序列號當作本身的seq序列號,確認號ack使用服務器的隨機號y再加1即ack=y+1,這樣客戶端就完成了第三次的驗證在講數據包發給服務器,服務器收到後驗證確認號是在本身的seq之上加了1,表示沒有問題就開始傳輸數據。
注:
ACK :TCP協議規定,只有ACK=1時有效,也規定鏈接創建後全部發送的報文的ACK必須爲1
Seq:序號,4字節,範圍爲0^32—1^32,共4284967296,達到時從新開始計算
在第三次的時候SYN等於0,由於SYN(SYNchronization) 只i在鏈接創建時用來同步序號,當SYN=1而ACK=0時,代表這是一個鏈接請求報文,對方若贊成創建鏈接,則應在響應報文中使SYN=1和ACK=1. 所以, SYN置1就表示這是一個鏈接請求或鏈接接受報文,鏈路創建成功以後就將標誌位置爲0。
SYN(synchronous創建聯機) ACK(acknowledgement 確認) PSH(push傳送) FIN(finish結束) RST(reset重置) URG(urgent緊急) Sequence number(順序號碼) Acknowledge number(確認號碼)
TCP三次握手、四次斷開與十一種狀態安全

四:TCP的四次斷開:

TCP斷開要四次是由於TCP傳輸數全雙工的,即數據是在同一時間內兩條數據鏈路雙向互相傳輸的,所以每一個方向都要單獨關閉一次,斷開須要客戶端到服務端斷開一次,而服務端到客戶端也須要斷開一次,這樣的斷開纔是完整的斷開,
第一次斷開:客戶方發給服務器一個FIN爲1的請求,FIN爲1表示是一個斷開鏈接的請求,即表示數據傳輸完畢請求斷開,併發送seq序列號和Ack確認號。
第二次斷開:服務器收到客戶端請求並返回ACK標誌位爲1,Ack爲Seq+1等於201,並將對方的Ack做爲本身的Seq序列號的確認數據包,biao 接收到請求贊成斷開。
第三次斷開:服務器發送ACK=1,FIN=1,Seq等於客戶端第一次請求斷開的Ack確認號+1,即Seq等於501的斷開請求給客戶端。
第四次斷開:客戶端發送ACK=1,Ack在上一步Seq上+1等於502,並使用在第二次斷開中服務器發送的Ack確號201做爲本次的序列號發給服務器表示贊成斷開,服務器收到後驗證序列號是第二次的,驗證Ack是第三次+1的,確認沒有問題後贊成斷開,而後將端口置爲TIME_WAIT狀態,等待2 MSL時間後置爲關閉狀態,被動方收到主動方的報文確認Ack確認號沒有問題後將端口置爲CLOSED,至此端口關閉。
SYN(synchronous創建聯機) ACK(acknowledgement 確認) PSH(push傳送) FIN(finish結束) RST(reset重置) URG(urgent緊急) Sequence number(順序號碼) Acknowledge number(確認號碼)
四次斷開的圖形示意以下:
TCP三次握手、四次斷開與十一種狀態服務器

五:TCP端口的十一種鏈接狀態:

TCP端口一共有十一種狀態,CLOSE_WAIT表示是程序y關閉鏈接,而TIME_WAIT只佔用一個socket鏈接,到時間以後會釋放,所以大量的CLOSE_WAIT是比大量的TIME_WAIT影響更大,另外還有FIN_WAIT1和FIN_WAIT2,若是有FIN_WAIT2也表示服務有問題,如下是每一個端口狀態的含義:
5.1:CLOSED:端口默認是關閉狀態。
5.2:LISTEN: 服務器程序開始監聽一個端口,就是LISTEN狀態。
5.3:SYN_RCVD:三次握手的第二次握手後的端口狀態,是收到了客戶端發送的SYN_SENT數據包以後的狀態,這個狀態很短暫,正常在服務器上是不多看到的,除非服務器故意不發送最後一次握手數據包,服務器返回給客戶端SYN確認以後就會將在本身的端口置爲SYN_RCVD。
5.4:SYN_SENT:SYN_SENT狀態表示客戶端已發送SYN=1的請求鏈接報文,發送以後客戶端就會將本身的端口狀態置爲SYN_SENT。
5.5:ESTABLISHED:表示已經鏈接成功,客戶端收到服務器的確認報文會回覆服務器,而後就將端口置爲ESTABLISHED,服務器第三次收到客戶端的Ack確認就會將端口置爲ESTABLISHED並開始傳輸數據。
5.6:FIN_WAIT_1:出如今主動關閉方,FIN_WAIT_1狀態其實是當SOCKET在ESTABLISHED狀態時,當任意一方想主動關閉鏈接,向對方發送了FIN=1的斷開鏈接請求報文,此時該SOCKET即 進入到FIN_WAIT_1狀態。而當對方迴應ACK報文後,則進入到FIN_WAIT_2狀態,固然在實際的正常狀況下,不管對方何種狀況下,都應該馬 上回應ACK報文,因此FIN_WAIT_1狀態通常是比較難見到的,而FIN_WAIT_2狀態還有時經常能夠用netstat看到。
5.7:FIN_WAIT_2:出如今主動關閉方,當被動方迴應FIN_WAIT_1的ACK報文後,則進入到FIN_WAIT_2狀態
5.8:TIME_WAIT:出如今主動關閉方,表示收到了對方的FIN請求關閉報文,併發送出了ACK報文,就等2MSL後便可回到CLOSED可用狀態了。若是FIN_WAIT_1狀態下,收到了對方同時帶FIN標誌和ACK標誌的報文時,能夠直接進入到TIME_WAIT狀態,而無須通過FIN_WAIT_2狀態。
5.9:CLOSING: 這種狀態比較特殊,實際狀況中應該是不多見,屬於一種比較罕見的例外狀態。正常狀況下,當你發送FIN報文後,按理來講是應該先收到(或同時收到)對方的 ACK報文,再收到對方的FIN報文。可是CLOSING狀態表示你發送FIN報文後,並無收到對方的ACK報文,反而卻也收到了對方的FIN報文。什 麼狀況下會出現此種狀況呢?其實細想一下,也不可貴出結論:那就是若是雙方几乎在同時close一個SOCKET的話,那麼就出現了雙方同時發送FIN報 文的狀況,也即會出現CLOSING狀態,表示雙方都正在關閉SOCKET鏈接。
5.10:CLOSE_WAIT: 表示在等待關閉端口,這種狀態存在於被動關閉的一方。
5.11:LAST_ACK: 是被動關閉方在主動關閉一方在發送FIN報文後,最後等待對方的ACK報文,當再次收到ACK報文後,也便可以進入到CLOSED可用狀態了。
5.12:區分主動斷開和被動端口方的端口狀態:
主動端口方:SYN_SENT、FIN_WAIT一、FIN_WAIT二、CLOSING、TIME_WAIT 。
被動斷開方:LISTEN、SYN_RCVD、CLOSE_WAIT、LAST_ACK 。
都具備的:CLOSED 、ESTABLISHED 。
TCP三次握手、四次斷開與十一種狀態
5.13:關於優化:
socket就是一個TCP鏈接,包括源地址、源端口、目標地址、目標端口和協議(TCP|UDP),0端口是保留不能使用的,所以服務器的最大端口使用數量爲63353個,最大65536個端口是由於TCP報文頭部有個端口長度爲2^16次方等於65536,查看當前打開的端口範圍# cat /proc/sys/net/ipv4/ip_local_port_range,單個IP地址能接受的最大併發爲六萬多,1萬個TIME_WAIT大約使用1MB的內存CPU佔用更小,所以資源使用很小能夠忽略不計,可是會佔用一個socket,能夠經過在負載上配置多個公網IP地址以提升高併發的問題,
[root@localhost ~]# cat /proc/sys/net/ipv4/tcp_tw_recycle
0 #用於快速回收處於TIME_WAIT狀態的socket以便從新分,在負載服務器不能打開,會致使經過nat上網的後續用戶沒法打開網頁,由於後面的訪問用戶時間戳小於前面的用戶,會致使數據包被負載服務器丟棄,能夠在內網使用,可是一般建議關閉。
[root@localhost ~]# cat /proc/sys/net/ipv4/tcp_tw_reuse
0 #kernel會複用處於TIME_WAIT狀態的socket,即容許將TIME_WAIT狀態得socket用於直接新的TCP鏈接,負載服務器建議打開
[root@localhost ~]# cat /proc/sys/net/ipv4/tcp_timestamps
1 #記錄數據包的時間戳,判斷是新的數據包仍是舊的,若是是舊的就丟棄,配合上面兩個選項的時候必定要打開才生效。網絡

六:Apache的工做模式:

Apache 2.X 支持插入式並行處理模塊,稱爲多路處理模塊(Multi-Processing Modules,MPM),在linux 系統,有3個不一樣類型的版本可供選擇,具體以下:
6.1:Prefork MPM: 預派生模式,有一個主控制進程,而後生成多個子進程,使用select模型,最大併發1024,每一個子進程有一個獨立的線程響應用戶請求,相對比較佔用內存,可是比較穩定,能夠設置最大和最小進程數,是最古老的一種模式,也是最穩定的模式,適用於訪問量不是很大的場景。
優勢:穩定
缺點:慢,佔用資源,不適用於高併發場景
TCP三次握手、四次斷開與十一種狀態
配置文件原內容:
#prefork MPM
#StartServers: number of server processes to start
#MinSpareServers: minimum number of server processes which are kept spare
#MaxSpareServers: maximum number of server processes which are kept spare
#MaxRequestWorkers: maximum number of server processes allowed to start
#MaxConnectionsPerChild: maximum number of connections a server process serves
#before terminating多線程

<IfModule mpm_prefork_module>
StartServers 5 #定義apache服務在啓動時啓動的子進程數量
MinSpareServers 5 #定義最小空閒進程數,空閒進程就是沒有處理用戶請求的進程數
MaxSpareServers 10 #定義最大空閒進程數
MaxRequestWorkers 250 #定義在prefork模式下的最大併發鏈接數,表示了apache的最大併發處理能力,超過的鏈接請求將被排隊等候處理。
MaxConnectionsPerChild 0 #進程生命週期內,處理的最大請求數目。達到該數目後,進程將死掉。若是設置爲0,表示沒有限制。該參數的意義在於,避免了可能存在的內存泄露帶來的系統問題。
</IfModule>併發

若是肯定合適的MaxRequestWorkers呢?
首先,經過top命令查看apache進程佔用的資源,主要看%CPU和%MEM這兩個指標,例如,每一個進程的CPU佔用率不超過1%,每一個進程的內存佔用率不超過2%,考慮內存限制,比較合適的apache進程數量爲50個,而後,逐步測試最大值。經過觀測得來的CPU和內存的指標有必定的偏差,通常能夠適當調節這個數值,例如調到1.5或者2倍,再經過峯值場景下的機器是否卡頓來判斷是繼續上調仍是下調。
6.2:woker MPM:是一種多進程和多線程混合的模型,有一個控制進程,啓動多個子進程,每一個子進程裏面包含固定的線程,使用線程程來處理請求,當線程不夠使用的時候會再啓動一個新的子進程,而後在進程裏面再啓動線程處理請求,因爲其使用了線程處理請求,所以能夠承受更高的併發。
TCP三次握手、四次斷開與十一種狀態
優勢:相比prefork 佔用的內存較少,能夠同時處理更多的請求
缺點:使用keep-alive的長鏈接方式,某個線程會一直被佔據,即便沒有傳輸數據,也須要一直等待到超時纔會被釋放。若是過多的線程,被這樣佔據,也會致使在高併發場景下的無服務線程可用。(該問題在prefork模式下,一樣會發生)
配置文件原內容詳解:
#worker MPM
#StartServers: initial number of server processes to start
#MinSpareThreads: minimum number of worker threads which are kept spare
#MaxSpareThreads: maximum number of worker threads which are kept spare
#ThreadsPerChild: constant number of worker threads in each server process
#MaxRequestWorkers: maximum number of worker threads
#MaxConnectionsPerChild: maximum number of connections a server process serves
#before terminating異步

<IfModule mpm_worker_module>
StartServers 3 # #定義apache服務在啓動時啓動的子進程數量,默認是3個
MinSpareThreads 75 # 整個控制進程保持最小數的空閒線程數
MaxSpareThreads 250 # 整個控制進程保持最大數的空閒線程數
#ThreadLimit 64 # 每一個子進程能夠啓動的線程數量上限值,默認沒有設置
ThreadsPerChild 25 # 每一個子進程啓動的線程默認數量,開啓啓動兩個子進程每一個子進程25個 線程,就是apache 啓動後開啓25個線程。
MaxRequestWorkers 400 # 全部子進程加起來的線程數量最大值,數量等於最大啓動的進程數*ThreadsPerChild(每一個進程的線程數)
MaxConnectionsPerChild 0 # 每一個子進程被請求多少次服務後被kill掉從新生成一個新的子進程,爲了解決內存回收方面的問題,0爲不設置
</IfModule>
6.3:event MPM:Apache中最新的模式,屬於事件驅動模型(epoll),每一個進程響應多個請求,在如今版本里的已是穩定可用的模式。它和worker模式很像,最大的區別在於,它解決了keep-alive場景下,長期被佔用的線程的資源浪費問題(某些線程由於被keep-alive,空掛在哪裏等待,中間幾乎沒有請求過來,甚至等到超時)。event MPM中,會有一個專門的線程來管理這些keep-alive類型的線程,當有真實請求過來的時候,將請求傳遞給服務線程,執行完畢後,又容許它釋放。這樣加強了高併發場景下的請求處理能力。
event只在有數據發送的時候纔開始創建鏈接,鏈接請求才會觸發工做線程,即便用了TCP的一個選項,叫作延遲接受鏈接TCP_DEFER_ACCEPT,加了這個選項後,若客戶端只進行TCP鏈接,不發送請求,則不會觸發Accept操做,也就不會觸發工做線程去幹活,進行了簡單的防***(TCP鏈接),可使用Telnet進行測試驗證:
主機192.168.10.130爲客戶端機器,192.168.10.131爲apache服務器機器使用event模式:
在192.168.10.130上telnet 192.168.10.131 80,而後在192.168.10.130客戶端機器上使用netstat查看,發現鏈接已經創建,處於ESTABLISHED狀態,而後再到apache服務器192.168.10.131使用netstat查看,發現是處於SYN_RECV狀態。
TCP三次握手、四次斷開與十一種狀態
優勢:單線程響應多請求,佔據更少的內存,高併發下表現更優秀,會有一個專門的線程來管理keep-alive類型的線程,當有真實請求過來的時候,將請求傳遞給服務線程,執行完畢後,又容許它釋放
缺點:沒有線程安全控制
配置文件內容:
#event MPM
#StartServers: initial number of server processes to start
#MinSpareThreads: minimum number of worker threads which are kept spare
#MaxSpareThreads: maximum number of worker threads which are kept spare
#ThreadsPerChild: constant number of worker threads in each server process
#MaxRequestWorkers: maximum number of worker threads
#MaxConnectionsPerChild: maximum number of connections a server process serves
#before terminating
<IfModule mpm_event_module>
StartServers 3 #apache服務啓動的子進程數,默認3個
MinSpareThreads 75 #控制進程保持最小的空閒線程數
MaxSpareThreads 250 #控制進程保持的最大空閒線程數
ThreadsPerChild 25 #每一個子進程啓動的線程數
MaxRequestWorkers 400 #併發最大請求數,也就是全部子進程加起來的線程數量,woker模式下的400就是併發400,可是因爲是異步處理請求的,所以這裏的400比woker模型下的併發處理速度要快不少,由於event省略了工做線程的會話保持。
MaxConnectionsPerChild 0 #每一個子進程請求多少次之後被kill掉從新生成一個新的子進程。
</IfModule>socket

相關文章
相關標籤/搜索