1. 程式人生 > 其它 >10-三次握手四次揮手

10-三次握手四次揮手

 三次握手

[root@Rocky ~]# ethtool ens33
    Link detected: yes  #埠正常

[root@Rocky ~]# rpm -ql netcat
/usr/bin/nc

ss -nutlp #檢視tcp udp連結埠和程序對應關係
來自於iproute包,代替netstat,netstat 通過遍歷 /proc來獲取 socket資訊,ss 使用 netlink與核心tcp_diag 模組通訊獲取 socket 資訊
-t: tcp協議相關
-u: udp協議相關
-w: 裸套接字相關
-x:unix sock相關
-l: listen狀態的連線
-a: 所有 -n: 數字格式 -p: 相關的程式及PID -e: 擴充套件的資訊 -m:記憶體用量 -o:計時器資訊
傳輸層通過port號,確定應用層協議,範圍0-65535
wang@ubuntu2004:~$ nc -l 1023
nc: Permission denied
0-1023:系統埠或特權埠(僅管理員可用) ,眾所周知,永久的分配給固定的系統應用使用,
22/tcp(ssh), 80/tcp(http), 443/tcp(https)
1024-49151:使用者埠或註冊埠,但要求並不嚴格,分配給程式註冊為某應用使用,
1433/tcp(SqlServer), 1521/tcp(oracle),3306
/tcp(mysql),11211/tcp/udp (memcached) 49152-65535:動態或私有埠,客戶端隨機使用埠,範圍定 義:/proc/sys/net/ipv4/ip_local_port_range 注意:當前6000,6665-6669/tcp等埠被Google Chrome 設為預設非安全埠,儘量避免使用 範例: 檢視非特權使用者可以使用起始埠
[root@Rocky yum.repos.d]# cat /proc/sys/net/ipv4/ip_unprivileged_port_start
1024
範例:調整客戶端的動態埠範圍
[root@Rocky ~]# cat /proc/sys/net/ipv4/ip_local_port_range
20000 62000

監聽22埠

[root@Rocky ~]# nc -l 222 
ss -tnl
LISTEN              0                   10                                        [::]:222
root@ubuntu2004:/etc/apt# nc 192.168.80.171 222
[root@Rocky ~]# ss -nt
State                  Recv-Q             Send-Q                          Local Address:Port                            Peer Address:Port              Process             
CLOSE-WAIT             32                 0                              192.168.80.171:44172                             8.43.85.13:443                                   
ESTAB                  0                  52                             192.168.80.171:22                              192.168.80.1:50060                                 
ESTAB                  0                  0                              192.168.80.171:222                           192.168.80.181:50882 #遠端計算機socket
root@ubuntu2004:/etc/apt# nc 192.168.80.171 222
I am ubuntu

 

 

ip.src == 192.168.80.171 and ip.dst==192.168.80.181

 

[root@Rocky ~]# ss -nt
State                  Recv-Q             Send-Q                          Local Address:Port                            Peer Address:Port              Process             
CLOSE-WAIT             32                 0                              192.168.80.171:44172                             8.43.85.13:443                                   
ESTAB                  0                  52                             192.168.80.171:22                              192.168.80.1:50060
root@ubuntu2004:~# ss -nt
State                  Recv-Q             Send-Q                          Local Address:Port                            Peer Address:Port              Process             
ESTAB                  0                  36                             192.168.80.181:22                              192.168.80.1:50065                                 
CLOSE-WAIT             0                  0                              192.168.80.181:50882                         192.168.80.171:222

 

tcpdump -n -t -S -i ens33  port 3334 -w tcp3.cap

 

-i : 指定抓包的網絡卡是enp0s3
-n: 把域名轉成IP顯示
-t: 不顯示時間
-S: 序列號使用絕對數值,不指定-S的話,序列號會使用相對的數值
port: 指定監聽埠是80
host:指定監聽的主機名

 

 

 

 

 三系握手過程

第一次握手

客戶端將TCP報文標誌位SYN置為1,隨機產生一個序號值seq=J,儲存在TCP首部的序列號(Sequence Number)欄位裡,指明客戶端打算連線的伺服器的埠,並將該資料包傳送給伺服器端,傳送完畢後,客戶端進入SYN_SENT狀態,等待伺服器端確認。

第二次握手

伺服器端收到資料包後由標誌位SYN=1知道客戶端請求建立連線,伺服器端將TCP報文標誌位SYN和ACK都置為1,ack=J+1,隨機產生一個序號值seq=K,並將該資料包傳送給客戶端以確認連線請求,伺服器端進入SYN_RCVD狀態。

第三次握手

客戶端收到確認後,檢查ack是否為J+1,ACK是否為1,如果正確則將標誌位ACK置為1,ack=K+1,並將該資料包傳送給伺服器端,伺服器端檢查ack是否為K+1,ACK是否為1,如果正確則連線建立成功,客戶端和伺服器端進入ESTABLISHED狀態,完成三次握手,隨後客戶端與伺服器端之間可以開始傳輸資料了。

 

 

 

為什麼需要三次握手?

我們假設client發出的第一個連線請求報文段並沒有丟失,而是在某個網路結點長時間的滯留了,以致延誤到連線釋放以後的某個時間才到達server。

本來這是一個早已失效的報文段。但server收到此失效的連線請求報文段後,就誤認為是client再次發出的一個新的連線請求。於是就向client發出確認報文段,同意建立連線。

假設不採用“三次握手”,那麼只要server發出確認,新的連線就建立了。由於現在client並沒有發出建立連線的請求,因此不會理睬server的確認,也不會向server傳送資料。但server卻以為新的運輸連線已經建立,並一直等待client發來資料。這樣,server的很多資源就白白浪費掉了。

所以,採用“三次握手”的辦法可以防止上述現象發生。例如剛才那種情況,client不會向server的確認發出確認。server由於收不到確認,就知道client並沒有要求建立連線。

TCP 四次揮手關閉連線

 由客戶端或服務端任一方執行close來觸發。
由於TCP連線是全雙工的,因此,每個方向都必須要單獨進行關閉,這一原則是當一方完成資料傳送任務後,傳送一個FIN來終止這一方向的連線,收到一個FIN只是意味著這一方向上沒有資料流動了,即不會再收到資料了,但是在這個TCP連線上仍然能夠傳送資料,直到這一方向也傳送了FIN。首先進行關閉的一方將執行主動關閉,而另一方則執行被動關閉。

四次揮手過程的示意圖如下:

 

 

揮手請求可以是Client端,也可以是Server端發起的,我們假設是Client端發起:

  • 第一次揮手: Client端發起揮手請求,向Server端傳送標誌位是FIN報文段,設定序列號seq,此時,Client端進入FIN_WAIT_1狀態,這表示Client端沒有資料要傳送給Server端了。
  • 第二次分手:Server端收到了Client端傳送的FIN報文段,向Client端返回一個標誌位是ACK的報文段,ack設為seq加1,Client端進入FIN_WAIT_2狀態,Server端告訴Client端,我確認並同意你的關閉請求。
  • 第三次分手: Server端向Client端傳送標誌位是FIN的報文段,請求關閉連線,同時Client端進入LAST_ACK狀態。
  • 第四次分手 : Client端收到Server端傳送的FIN報文段,向Server端傳送標誌位是ACK的報文段,然後Client端進入TIME_WAIT狀態。Server端收到Client端的ACK報文段以後,就關閉連線。此時,Client端等待2MSL的時間後依然沒有收到回覆,則證明Server端已正常關閉,那好,Client端也可以關閉連線了。

為什麼連線的時候是三次握手,關閉的時候卻是四次握手?

建立連線時因為當Server端收到Client端的SYN連線請求報文後,可以直接傳送SYN+ACK報文。其中ACK報文是用來應答的,SYN報文是用來同步的。所以建立連線只需要三次握手。

由於TCP協議是一種面向連線的、可靠的、基於位元組流的運輸層通訊協議,TCP是全雙工模式
這就意味著,關閉連線時,當Client端發出FIN報文段時,只是表示Client端告訴Server端資料已經發送完畢了。當Server端收到FIN報文並返回ACK報文段,表示它已經知道Client端沒有資料傳送了,但是Server端還是可以傳送資料到Client端的,所以Server很可能並不會立即關閉SOCKET,直到Server端把資料也傳送完畢。
當Server端也傳送了FIN報文段時,這個時候就表示Server端也沒有資料要傳送了,就會告訴Client端,我也沒有資料要傳送了,之後彼此就會愉快的中斷這次TCP連線。

為什麼要等待2MSL?

MSL:報文段最大生存時間,它是任何報文段被丟棄前在網路內的最長時間。
有以下兩個原因:

第一點:保證TCP協議的全雙工連線能夠可靠關閉

由於IP協議的不可靠性或者是其它網路原因,導致了Server端沒有收到Client端的ACK報文,那麼Server端就會在超時之後重新發送FIN,如果此時Client端的連線已經關閉處於CLOESD狀態,那麼重發的FIN就找不到對應的連線了,從而導致連線錯亂,所以,Client端傳送完最後的ACK不能直接進入CLOSED狀態,而要保持TIME_WAIT,當再次收到FIN的收,能夠保證對方收到ACK,最後正確關閉連線。

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

如果Client端傳送最後的ACK直接進入CLOSED狀態,然後又再向Server端發起一個新連線,這時不能保證新連線的與剛關閉的連線的埠號是不同的,也就是新連線和老連線的埠號可能一樣了,那麼就可能出現問題:如果前一次的連線某些資料滯留在網路中,這些延遲資料在建立新連線後到達Client端,由於新老連線的埠號和IP都一樣,TCP協議就認為延遲資料是屬於新連線的,新連線就會接收到髒資料,這樣就會導致資料包混亂。所以TCP連線需要在TIME_WAIT狀態等待2倍MSL,才能保證本次連線的所有資料在網路中消失。