TCP的三次握手四次揮手

2022-09-15 22:03:27 字數 3798 閱讀 1100

注意標誌位:

1).同步 syn = 1 表示這是乙個連線請求或連線接受報文。 

2).只有當 ack = 1 時確認號字段才有效。當 ack = 0 時,確認號無效。 

3).fin = 1 表明此報文段的傳送端的資料已傳送完畢,並要求釋放運輸連線。 

為什麼建立連線協議是三次握手,而關閉連線卻是四次握手呢?

這是因為服務端的listen狀態下的socket當收到syn報文的建連請求後,它可以把ack和syn(ack起應答作用,而syn起同步作用)

放在乙個報文裡來傳送。但關閉連線時,當收到對方的fin報文通知時,它僅僅表示對方沒有資料傳送給你了;但未必你所有的資料都全部

傳送給對方了,所以你可以未必會馬上會關閉socket,也即你可能還需要傳送一些資料給對方之後,再傳送fin報文給對方來表示你同意

現在可以關閉連線了,所以它這裡的ack報文和fin報文多數情況下都是分開傳送的。

更明了的回答:由於tcp連線是全雙工的,因此每個方向都必須單獨進行關閉。這個原則是當一方完成它的資料傳送任務後就能傳送一

個fin來終止這個方向的連線。收到乙個 fin只意味著這一方向上沒有資料流動,乙個tcp連線在收到乙個fin後仍能傳送資料。首先進行

關閉的一方將執行主動關閉,而另一方執行被動關閉。

第一階段

首先client會傳送乙個fin包給server(同時還有ack和seq包),這是要告訴server,我已經沒有資料要發給你了,此時client處於fin_wait_1狀態。接收到fin包的server處於close_wait的狀態。

server發回乙個ack(值為client傳過來的seq+1)和seq(值為client傳過來的ack的值)給client。client收到server發過來的包後確認關閉連線,此時client處於fin_wait_2。

第二階段

server在接收到client的fin後,得知client要斷開tcp連線了,於是在傳送完ack和seq給client後,自己傳送乙個fin包給client(也帶有ack和seq包),告訴client我也要斷開連線了,此時server處於last_ack狀態。

client接收到server的fin資訊後,會回覆server乙個ack包,並且會進入time_wait狀態,持續2個msl(max segment lifetime)。而server接收到client ack後便關閉連線。client在指定時間過後仍然沒有接收到server的資料,確認server已經沒有資料過來,也關閉了連線。

(1)、close_wait的解釋。

在以上事例,我們知道server在接收到fin後,傳送ack之前會進入close_wait,如果長期處於這個狀態,或者說伺服器出現大量close_wait,說明ack包一直沒有發出,這時候就應該檢查**了。

(2)、time_wait注意事項

從事例我們知道,主動關閉連線的一方會經歷time_wait狀態,在該狀態下的socket是不會被**的。而如果是伺服器端主動關閉連線,則可能會面臨處於大量time_wait的情況(因為連線很多嘛),會嚴重影響伺服器的處理能力。

怎麼解決呢,那就減少伺服器端time_wait的時間咯。

(3)2msl(maximum segment lifetime)存在的理由

tcp的time_wait狀態也稱為2msl等待狀態

(4)2msl狀態為什麼設計在主動關閉這一方

(1)發最後ack的是主動關閉一方

(2)只要有一方保持time_wait狀態,就能起到避免incarnation connection在2msl內的重新建立,不需要兩方都有

主動關閉tcp/ip連線,會通過time_wait的狀態保留一段時間,時間過了才會釋放這個埠,當埠接受的頻繁請求數量過多的時候,

就會產生大量的time_wait狀態的連線,這些連線佔著埠,會消耗大量的資源。

這個time_wait的作用是什麼?

原因有二:

一、保證tcp協議的全雙工連線能夠可靠關閉

如果client直接closed了,那麼由於ip協議的不可靠性或者是其它網路原因,導致server沒有收到client最後回覆的ack。那麼server就會在超時之後繼續傳送fin。 此時由於client已經closed了,就找不到與重發的fin對應的連線,最後server就會收到rst而不是ack,server就會以為是連線錯誤把問題報告給高層。 這樣的情況雖然不會造成資料丟失,但是卻導致tcp協議不符合可靠連線的要求。 所以,client不是直接進入closed,而是要保持time_wait,當再次收到fin的時候,能夠保證對方收到ack,最後正確的關閉連線。 

二、保證這次連線的重複資料段從網路中消失

如果client直接closed,然後又再向server發起乙個新連線,我們不能保證這個新連線與剛關閉的連線的埠號是不同的。也就是說有可能新連線和老連線的埠號是相同的。

一般來說不會發生什麼問題,但是還是有特殊情況出現:假設新連線和已經關閉的老連線埠號是一樣的,如果前一次連線的某些資料仍然滯留在網路中,這些延遲資料在建立新連線之後才到達server,由於新連線和老連線的埠號是一樣的,又因為tcp協議判斷不同連線的依據是socket pair。

於是,tcp協議就認為那個延遲的資料是屬於新連線的,這樣就和真正的新連線的資料報發生混淆了。

vi /etc/sysctl.conf

#當出現syn等待佇列溢位時,啟用cookies來處理,可防範少量syn攻擊

net.ipv4.tcp_syncookies = 1

#允許將time-wait sockets重新用於新的tcp連線,預設為0

net.ipv4.tcp_tw_reuse = 1

#開啟tcp連線中time-wait sockets的快速**,預設為0,表示關閉

net.ipv4.tcp_tw_recycle = 1

# 預設60

net.ipv4.tcp_fin_timeout = 30

/sbin/sysctl -p

此外,如果你的連線數本身就很多,我們可以再優化一下tcp/ip的可使用埠範圍,進一步提公升伺服器的併發能力。

net.ipv4.tcp_keepalive_time = 1200

表示當keepalive起用的時候,tcp傳送keepalive訊息的頻度。預設是2小時,改為20分鐘。

net.ipv4.ip_local_port_range = 10000 65000

表示用於向外連線的埠範圍。預設情況下很小:32768到61000,改為10000到65000。設的太低,否則可能會占用掉正常的埠

net.ipv4.tcp_max_syn_backlog = 8192

表示syn佇列的長度,預設為1024,加大佇列長度為8192,可以容納更多等待連線的網路連線數。

net.ipv4.tcp_max_tw_buckets = 5000

表示系統同時保持time_wait的最大數量,如果超過這個數字,time_wait將立刻被清除並列印警告資訊。預設為180000,改為5000。對於apache、nginx等伺服器,上幾行的引數可以很好地減少time_wait套接字數量。

參考:tcp連線的建立和釋放

TCP三次握手 四次揮手

tcp 三次握手 tcp 連線是通過三次握手進行初始化的。三次握手的目的是同步連線雙方的序列號和確認號並交換 tcp 視窗大小資訊。以下步驟概述了通常情況下客戶端計算機聯絡伺服器計算機的過程 1.客戶端向伺服器傳送乙個syn置位的tcp報文,其中包含連線的初始序列號x和乙個視窗大小 表示客戶端上用來...

TCP三次握手 四次揮手

服務端的tcp程序先建立傳輸控制塊tcb,準備接受客戶端程序的連線請求,然後服務端程序處於listen狀態,等待客戶端的連線請求,如有,則作出響應。1 客戶端的tcp程序也首先建立傳輸控制模組tcb,然後向服務端發出連線請求報文段,該報文段首部中的syn 1,ack 0,同時選擇乙個初始序號seq ...

TCP三次握手四次揮手

tcp transmission control protocol 傳輸控制協議 tcp是主機對主機層的傳輸控制協議,提供可靠的連線服務,採用三次握手確認建立乙個連線。位碼即tcp標誌位,有6種標誌 urg urgent緊急 ack acknowledgement 確認 psh push傳送 rst...