日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

连接状态_TCP 连接状态及相关命令学习

發布時間:2023/11/27 生活经验 55 豆豆
生活随笔 收集整理的這篇文章主要介紹了 连接状态_TCP 连接状态及相关命令学习 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在平時的開發工作中,我們都使用被封裝完好的 TCP/HTTP 庫去完成需求開發,很少關心底層 TCP 的連接狀態,但是一旦遇到較難定位的線上事故,往往都是因為 TCP 連接參數或者使用姿勢不對導致的,本文對 TCP 連接狀態以及相關命令做一下梳理總結:

什么是 TCP 協議

  • 位于 OSI 模型中的傳輸層(第四層),是一種端對端的傳輸協議
  • 面向連接的、可靠的協議
  • 通過校驗和、序列號、確認應答、重發控制、窗口控制等機制實現可靠傳輸
  • 由建立連接、數據傳輸和連接釋放三個階段組成
  • 采用三次握手建立連接,采用四次揮手關閉連接

想了解 TCP 的連接狀態,必須先理清楚 TCP 的三次握手和四次揮手是怎么回事,下圖關于 TCP 三次握手和四次揮手的狀態轉換圖(圖片來自于知乎文章 《“三次握手,四次揮手”你真的懂嗎?》):

這里不要把圖里的 Client/Server 和項目里的客戶端服務器端混淆,主動發起連接的一方或者主動關閉連接的一方就是 Client,被動的一方便為 Server。一個服務既可以充當 Client 的角色,也可以充當 Server 的角色。

TCP 的三次握手

三次握手為了使 Client 和 Server 都確認是否有接受對方的數據和發送數據給對方的能力:

  • 第一次握手:Client 先發送一個 SYN(j) 包作為建立連接的請求,確認自己的發送能力是否正常
  • 第二次握手:Server 針對 Client 的 SYN 包回復一個 ACK(j + 1) 包確認應答,同時發送 SYN(k) 包給 Client 表示要求建立連接,在明確自己有接收能力的同時確認一下自己的發送能力
  • 第三次握手:Client 收到 SYN + ACK 包后發送 ACK(k + 1) 包確認應答,表示自己的接收能力正常,此時完成三次握手建立可靠的連接

TCP 的四次揮手

四次揮手主要是為了讓 Client 和 Server 雙方都可以正常關閉連接,保證關閉連接前不丟失數據:

  • 第一次揮手:Client 先發送一個 FIN 包表示請求斷開連接
  • 第二次揮手:當 Server 收到 FIN 包后,立即回復 ACK 進行確認應答,表示我已經收到你關閉連接的請求,此時 Server 還有接收數據的能力
  • 第三次揮手:一段時間后,當 Server 端確認 Client 端的數據已經接受完畢,發送一個 FIN 包表示關閉連接,不再接收數據
  • 第四次揮手:當 Client 收到 FIN 后,立即回復一個 ACK 進行確認,然后等待 2MSL 后關閉連接

TCP 的連接狀態

在 TCP 的三次握手、數據傳輸以及四次揮手的過程中,我們給 Client 和 Server 定義了很多狀態用于描述整個流程,結合上面的狀態轉換圖來理解這些狀態定義:

  • LISTEN(Server): 正在偵聽來自遠方的 TCP 端口的連接請求,服務端啟動后處于 LISTEN 狀態用于監聽不同客戶端的 TCP 請求并建立連接
  • SYN-SENT(Client): 三次握手時,Client 在發送 SYN 以請求后處于等待建立連接的狀態
  • SYN_RCVD(Server):三次握手時,當 Server 收到 Client 的 SYN 信號時,將標志位 ACK 和 SYN 發送給 Client 后到建立連接之間,Server 處于 SYN_RCVD 狀態
  • ESTABLISHED(Server And Client):三次握手成功以后,Client 和 Server 處于數據傳輸的狀態
  • FIN-WAIT-1(Client):四次揮手時,Client 端發送中斷請求 FIN 到收到 Server 端的中斷確認的過程
  • CLOSE_WAIT(Server):四次揮手時,Client 接收到 Client 的 FIN 請求響應后回復 ACK 確認到發送 FIN 包的狀態
  • FIN-WAIT-2(Client):四次揮手時,當 Client 接收到 Server 對于 FIN 的響應 ACK 后到收到 Server 端的 FIN 包的狀態
  • LAST_ACK(Server):四次揮手時,Server 發送 FIN 請求關閉連接到關閉連接前的狀態
  • TIME_WAIT(Client):四次揮手時 Client 對于 Server 的 FIN 回復 ACK 到連接關閉前的狀態,又稱 2MSL 狀態
  • CLOSE(Server And Client):Server 和 CLient 關閉連接后的狀態

正常情況下,客戶端的狀態轉換流程如下:

CLOSED -> SYN_SENT -> ESTABLISHED -> FIN_WAIT_1 -> FIN_WAIT_2 -> TIME_WAIT -> CLOSED

正常情況下,服務端的狀態轉換流程如下:

CLOSED -> LISTEN -> SYN_RCVD -> ESTABLISHED -> CLOSE_WAIT -> LAST_ACK -> CLOSED

關于 TCP 三次握手和四次揮手狀態轉換中的一些問題

  • 什么是 MSL ?
- MSL 全稱是 maximum segment lifetime,報文最大生存時間
- MSL 是任何 IP 數據報能夠在因特網存活的最長時間,超過這個時間報文將被丟棄
- MSL 的具體值通常為 30 秒或者是 2 分鐘
  • 什么是 TTL ?
- TTL(time to live) 通常表示在數據傳輸中,包在被丟棄前最多能經過的路由器個數
- 每經過一個路由器都至少要把 TTL 減 1,當記數到 0 時,路由器決定丟棄該包,并發送一個 ICMP 報文給最初的發送者(表示不可達)
- TTL 是由發送主機設置的,以防止數據包不斷在 IP 互聯網絡上永不終止地循環
- TTL 的值可以修改,但是不能超過 256,一般是 64,128...
- ping 命令返回的 TTL 值表示當包達到目標主機時,還剩下的 TTL 值,所以假設系統 TTL 值是 64,ping 出來的 TTL 結果是 58,那么從源主機到達目標主機需要經過 64 - 58 = 6 次跳轉
- traceroute 在追蹤網絡數據包傳輸路由時,也可以通過參數 -m 指定 TTL,表示經過的網關最大數量
  • 什么是 RTT ?
- RTT 是客戶到服務器往返所花時間(round-trip time,簡稱RTT)
- TCP 含有動態估算 RTT 的算法,TCP 還持續估算一個給定連接的 RTT,因為 RTT 受網絡傳輸擁塞程序的變化而變化
  • 什么是 MTU ?
- Maximum Transmit Unit(最大傳輸單元),即物理接口(數據鏈路層)提供給其上層最大一次傳輸數據的大小
- 每個網絡接口都可以設置自己的 MTU 值,默認值一般為 1500,表示整個 IP 包從這個接口最大可以發送 1500 個字節
- 因為一般情況下 IP 層傳輸的數據大于 MTU 值,需要需要采用分片技術進行傳輸
- 路徑 MTU:任意兩臺主機之間的 MTU 不一定相同,因為數據在傳輸中會經過多臺主機,需要找出所有路徑中最小的 MTU(路徑 MTU)進行傳輸否則數據傳輸會失敗,一般通過 ICMP 協議進行路徑 MTU 的發現
  • 什么是 MSS ?
- Maximum Segment Size(最大分段大小), 不包含 TCP Header 和 TCP Option,只包含 TCP Payload
- MSS 是 TCP 用來限制應用層最大的發送字節數,如果底層物理接口 MTU = 1500 byte,則 MSS = 1500- 20(IP Header) -20 (TCP Header) = 1460 byte
  • 為什么建立連接協議是三次握手,而關閉連接卻是四次揮手呢?
主要是因為建立連接之前雙方都沒有任何數據傳輸發生,雙方處于干凈的狀態,所以 Server 可以直接把 ACK 和 SYN 放在一個數據包里發送到 Client,
少一次數據傳輸的過程。而四次揮手時,Client 發送了 FIN 報文,僅僅表示 Client 已經沒有數據要發送給 Server 了,但是 Client 仍然可以接受數據,
所以當 Server 收到 Client 數據的 FIN 報文后,它可以對于 FIN 請求進行應答(ACK),但是不能同時發送 FIN 也請求關閉連接,因為此時可能存在沒有
傳輸完的數據,而一旦發送 FIN 報文就意味著要停止發送數據,所以需要等待數據傳輸完再發送 FIN 報文,因此需要四次揮手。
  • 四次揮手時,Client 完成對于 Server 的 ACK 后為什么不立即關閉連接,要存在一個 TIME_WAIT(2MSL) 狀態?
之所以要等待這個狀態主要有兩個原因:
- 最后一次揮手數據很有可能丟失,維持這個狀態主要為了可以繼續重發 ACK
- 因為 TCP 發送出去的包和接收到的包順序不一定保持一致,如果 Server 先發出去的包延遲到達后,Client 將收不到,并且會干擾新建立的連接
  • 如果服務器上存在大量 TIME_WAIT 情況,如何改善?
如果出現 TIME_WAIT 狀態一般因為客戶端頻繁的建立和關閉連接,從而可能影響后續連接的建立,這種情況一般可以通過調節系統參數優化,修改這些參數要慎重:
- tcp_tw_recycle:表示開啟 TCP 連接中 TIME-WAIT sockets 的快速回收
- tcp_tw_reuse:表示開啟重用。允許將 TIME-WAIT sockets 重新用于新的 TCP 連接
- tcp_max_tw_buckets:指定系統在同一時間最多能有多少 TIME_WAIT 狀態,當超過這個值時,系統會直接干掉 TIME_WAIT 的 socket
  • 如果服務器上存在大量 CLOSE_WAIT 情況,如何改善?
- 存在大量 CLOSE_WAIT 狀態一般都是自身代碼的原因,所以首先還是從自身的代碼出發,不要隨便甩鍋
- 一般是因為服務器調用第三方應用(mysql, redis等)時,處理完結果忘記關閉連接,導致第三方應用因為超時發起主動關閉,而服務器無響應進而出現大量 CLOSE_WAIT 狀態
- 例如在 mysql 連接過程中,sql 回滾或者提交時忘記關閉與 mysql 的連接,導致 mysql 因為超時主動關閉連接,就會大量 CLOSE_WAIT 的狀態
- 例如在 javascript 中同步和異步代碼亂用,導致處理完請求后無法回調錯誤引起超時

SYN FLOOD 攻擊

  • 什么是 SYN FLOOD 攻擊:

在進行三次握手時,攻擊軟件向被攻擊的服務器發送 SYN 連接請求(三次握手的第一步),但是客戶端的地址是偽造的,服務器在收到連接請求時將標志位 ACK 和 SYN 發送給客戶端(三次握手的第二步),但是由于這些客戶端的 IP 地址都是偽造的,服務器根本找不到客戶端,導致出現大量握手失敗的情況。這種情況下服務器端一般會選擇重試(再次發送 SYN+ACK 給客戶端)并等待一段時間后丟棄這個未完成的連接,這段時間的長度我們稱為 SYN Timeout,服務器端將為了維護一個非常大的半連接列表而消耗非常多的資源,消耗非常多的 CPU 時間和內存,可能導致服務器失去響應,SYN FLOOD 攻擊就達到目的。

  • 如何防御 SYN FLOOD 攻擊:
1. 可以減少半開狀態下等待 ACK 消息的時間 
2. 減少重試發送 SYN-ACK 消息的次數 
3. 部署支持“ IP 防偽”的路由器,將偽造過 IP 地址的 SYN 消息直接過濾掉
4. SYN Cache:分多個 SYN 緩存 Bucket,進入每個 Bucket 是隨機的,每個 bucket 處于 SYN 的連接個數有限,超過限制就踢出先加入的 SYN 連接,攻擊者很難均勻填滿所有 Bucket
5. SYN Cookies:服務端通過特定的算法把半開連接信息編碼成 “Cookie”,用作服務端給客戶端的消息編號(SequenceNum),隨 SYN-ACK消息一同返回給連接發起方客戶端,這樣在連接完全建立前服務端不保存任何信息。也不用一直等待,缺點是服務端喪失了重發 SYN-ACK 的能力

關于 Socket

  • 一個 TCP 連接對應一個 Socket
  • 一個 Socket 的唯一標識是: {SRC-IP, SRC-PORT, DEST-IP, DEST-PORT, PROTOCOL}
  • 一個處于監聽狀態的 TCP 服務可以同時接口來自多個客戶端的 Socket
  • 不同進程可以監聽同一個端口,如果他們的協議(TCP/UDP)不同
  • 一個進程可以打開和關閉多個 Socket
  • 子進程可以繼承所有的文件描述符(FD)從父進程上,所以不同的進程或者線程之間如果有父子關系,可以使用同一個Socket
  • 一個處于監聽狀態的 TCP 服務只需要一個監聽端口,但可以建立多個 Socket
  • 服務器一個端口可以創建的 socket 連接數理論上是沒有上限的,取決于系統的內存大小和可以創建的文件描述符的上限,可以通過修改文件描述符上限進行設置

TCP 連接中的相關命令

netstat 命令

netstat 用于打印網絡連接、路由表、連接的數據統計等,我們上文中介紹的各種連接狀態都可以通過該命令進行統計

  • 參數介紹
- -a:列出所有狀態的連接
- -l:列出正在監聽狀態(State=LISTEN的連接
- -t:列出所有 tcp 協議的連接
- -u:列出所有 udp 協議的連接
- -n: 開啟域名解析,將對應的域名解析為 IP
- -p:列出正在監聽的進程名稱和進程 PID(PID/Program name),在 root 用戶下啟動的進程,普通用戶是查不到對應的進程名稱的
- -e:列出進程對應的用戶 ID 或者用戶(USER),是用戶 ID 還是用戶名由 -n 參數決定
- -s:打印每種協議網絡包統計數據
- -r:打印內核路由信息
- -i:打印網絡接口信息,同 ifconfig 命令
  • 列出所有 tcp 的連接:
$ netstat -antActive Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State
tcp        0      0 127.0.0.1:15778         0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:514             0.0.0.0:*               LISTEN
tcp        0      0 10.122.139.165:62411    10.199.136.43:80        ESTABLISHED
tcp        0      0 106.2.124.34:443        115.236.119.139:39120   ESTABLISHED
...
  • 只列出處于監聽狀態的連接:
$ netstat -tnlActive Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State
tcp        0      0 127.0.0.1:15778         0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:514             0.0.0.0:*               LISTEN
...
  • 查看監聽中的進程名和用戶名
$ netstat -tnl(Not all processes could be identified, non-owned process infowill not be shown, you would have to be root to see it all.)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       User       Inode       PID/Program name
tcp        0      0 localhost:15778         *:*                     LISTEN      root       538503951   -
tcp        0      0 *:shell                 *:*                     LISTEN      root       509846560   -
tcp        0      0 localhost:15779         *:*                     LISTEN      root       538504573   -
  • 查看網絡接口:

和 ifconfig 和 ip a 的效果一樣

$ netstat -ie
  • 統計 TCP 每個連接狀態信息:
$ netstat -n | awk `/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}`LAST_ACK 5
SYN_RECV 30
ESTABLISHED 15
FIN_WAIT1 51
FIN_WAIT2 5
TIME_WAIT 10

ping 命令

ping 命令用于測試到達目的主機的網絡是否可用,可以接收域名或者 ip,不能檢查端口,工作在 OSI 參考模型的第三層-網絡層

ping 命令和 traceroute 命令一樣都是通過 ICMP 協議實現的,盡管 ping 工具也可以進行偵測,但是因為 ip 頭的限制,ping 不能完全的記錄下所經過的路由器。所以 traceroute 正好就填補了這個缺憾,所以如果想查詢整個路由信息還是需要 traceroute

# 直接 ping ip
$ ping 10.165.124.134
PING 10.165.124.134 (10.165.124.134): 56 data bytes
64 bytes from 10.165.124.134: icmp_seq=0 ttl=63 time=3.923 ms
64 bytes from 10.165.124.134: icmp_seq=1 ttl=63 time=4.103 ms# ping域名,可以獲取到指定域名的 ip
$ ping dev.youdata.com
PING dev.youdata.com (106.2.44.33): 56 data bytes
64 bytes from 106.2.44.33: icmp_seq=0 ttl=58 time=3.477 ms
64 bytes from 106.2.44.33: icmp_seq=1 ttl=58 time=3.904 ms
64 bytes from 106.2.44.33: icmp_seq=2 ttl=58 time=3.878 ms// -c 參數指定發送包的個數
$ ping -c 2 dev.youdata.com// -W 參數指定 ping 命令的等待時間
$ ping -W 2 dev.youdata.com

traceroute 命令

raceroute 原理是利用 ICMP 的 ttl expired 通知機制,每次通過不斷增加 ttl 從而不斷發現下一跳路由,traceroute 發送的是端口號 > 30000 的數據報,所以到達目的主機的時候,會收到端口不可達的 ICMP 回應,這個時候源主機就知道主機可以連通了。

$ traceroute www.baidu.com
traceroute to www.baidu.com (61.135.169.125), 30 hops max, 40 byte packets1  192.168.74.2 (192.168.74.2)  2.606 ms  2.771 ms  2.950 ms2  211.151.56.57 (211.151.56.57)  0.596 ms  0.598 ms  0.591 ms3  211.151.227.206 (211.151.227.206)  0.546 ms  0.544 ms  0.538 ms4  210.77.139.145 (210.77.139.145)  0.710 ms  0.748 ms  0.801 ms5  202.106.42.101 (202.106.42.101)  6.759 ms  6.945 ms  7.107 ms6  61.148.154.97 (61.148.154.97)  718.908 ms * bt-228-025.bta.net.cn (202.106.228.25)  5.177 ms7  124.65.58.213 (124.65.58.213)  4.343 ms  4.336 ms  4.367 ms8  202.106.35.190 (202.106.35.190)  1.795 ms 61.148.156.138 (61.148.156.138)  1.899 ms  1.951 ms9  * * *
30  * * *
  • raceroute 命令可以讓你實現追蹤網絡數據包的路由途徑,以及每個網關消耗的時間,預設數據包大小是 40 Bytes
  • raceroute 輸出結果會看到有一些行是以星號表示的記錄,可能是因為防火墻封掉了 ICMP 的返回信息,所以我們得不到什么相關的數據包返回數據
  • 每次數據包由某一同樣的出發點(source)到達某一同樣的目的地(destination)走的路徑可能會不一樣,但基本上來說大部分時候所走的路由是相同的
  • 每個跳躍點默認情況下會發送 3 次數據包,但是不一定會是同一個 ip,因為兩個網關之間也有可能有負載均衡策略,所以有些記錄中可能會有 2 個或者 3 個 ip
  • ip 頭所能紀錄的路由列表是非常有限的,所以 traceroute 采取不斷增加 ttl 的方式去發送,這也正是 traceroute 越到后面記錄返回越慢的原因
  • 主要參數說明:
-q: 探測數據包向每個網關發送數據包的個數,默認是 3 次,會記錄每次的時間長度
-m: 設置數據包經過網關的最大個數(TTL) 
-n: 顯示 ip,不查主機名

lsof 命令

lsof(list open files)是一個查看當前系統文件的工具。在 linux 環境下,任何事物都以文件的形式存在,通過文件不僅僅可以訪問常規數據,還可以訪問網絡連接和硬件。例如傳輸控制協議 (TCP) 和用戶數據報協議 (UDP) 套接字等,系統都會在后臺都為該應用程序分配了一個文件描述符,該文件描述符提供了大量關于這個應用程序本身的信息。

  • 參數說明
- -a: 列出打開文件存在的進程查找某個文件相關的進程
- -c<進程名>: 列出指定進程所打開的文件
- -g:列出GID號進程詳情
- -d<文件號>: 列出占用該文件號的進程
- +d<目錄>: 列出目錄下被打開的文件
- +D<目錄>: 遞歸列出目錄下被打開的文件
- -n<目錄>: 列出使用NFS的文件
- -i<條件>: 列出符合條件的進程。(4、6、協議、:端口、 @ip )
- -p<進程號>: 列出指定進程號所打開的文件
- -u: 列出UID號進程詳情
- -h: 顯示幫助信息
- -v: 顯示版本信息
  • 查找某個文件相關的進程
$ lsof /bin/bash
  • 列出某個用戶打開的文件信息
$ lsof -u username
  • 列出某個程序進程所打開的文件信息
$ lsof -c mysql
  • 通過某個進程號顯示該進程打開的文件
$ lsof -p 11968
  • 列出所有 tcp 網絡連接信息
$ lsof -i tcp
  • 列出某個端口被哪個進程占用
$ lsof -i :3306

telnet 命令

  • telnet 命令用于登錄遠程主機
  • telnet 因為采用明文傳送報文,安全性不好,很多 Linux 服務器都不開放 telnet 服務,而改用更安全的 ssh 方式
  • telnet 位于 OSI 模型的第七層(應用層)的一種協議
  • telnet ip port 用于測試遠程主機的某個端口是否開放,而 ping 命令是測試遠程主機網絡是否能通

參考文獻

  • 線上大量CLOSE_WAIT的原因深入分析
  • 又見CLOSE_WAIT
  • 再敘TIME_WAIT
  • 每天一個linux命令(55):traceroute命令
  • ping 原理與ICMP協議
  • netstat 的10個基本用法
  • 什么是SYN Flood攻擊?
  • 由 socket 的 accept 說開去
  • How do multiple clients connect simultaneously to one port, say 80, on a server? [duplicate]
  • TCP 連接的狀態詳解以及故障排查
  • lsof 一切皆文件

總結

以上是生活随笔為你收集整理的连接状态_TCP 连接状态及相关命令学习的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。