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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

TCP的状态转换及生产问题实操

發布時間:2024/1/17 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 TCP的状态转换及生产问题实操 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前文介紹了TCP協議主要的流程,包括建立連接、傳輸數據和斷開連接。如果大家認真閱讀了附圖,應該可以看到在各個流程中套接字的狀態是在不斷變化的,不同的狀態標識了套集字所處的階段。

如圖1是TCP一個完整的狀態轉換圖,圖中包含了套接字的所有狀態,以及發生狀態轉變的觸發條件。可能會有人問,了解這些狀態有什么用呢?我們平時編程又用不到。

圖1 TCP狀態轉換圖

為了說明上述問題,我們從3個角度進行解釋,分別是各種狀態的含義、在系統層面如何查詢狀態和在實際生產中的應用。

一、各種狀態的含義

在回答問題之前我們先具體了解一下各個狀態的含義。

  • CLOSED:這個是套接字的初始狀態,表示TCP連接是新建“未打開的”狀態或者已經“關閉著的”。
  • LISTEN :這個是服務端僅有的狀態,表示服務器端的某個SOCKET處于監聽狀態,可以接受客戶端的連接。
  • SYN_RCVD :表示服務器接收到了來自客戶端請求連接的SYN報文。在正常情況下,這個狀態我們可能觀察不到,因為這個狀態是服務器端的SOCKET在建立TCP連接時的三次握手會話過程中的一個中間狀態,很短暫。
  • SYN_SENT :這個狀態與SYN_RCVD 狀態相呼應,當客戶端SOCKET執行connect()進行連接時,它首先發送SYN報文,然后隨即進入到SYN_SENT 狀態,并等待服務端的發送三次握手中的第2個報文。SYN_SENT 狀態表示客戶端已發送SYN報文。
  • ESTABLISHED :表示TCP連接已經成功建立。
  • FIN_WAIT_1 :這個狀態得好好解釋一下,其實FIN_WAIT_1 和FIN_WAIT_2 兩種狀態的真正含義都是表示等待對方的FIN報文。而這兩種狀態的區別是:FIN_WAIT_1狀態實際上是當SOCKET在ESTABLISHED狀態時,它想主動關閉連接,向對方發送了FIN報文,此時該SOCKET進入到FIN_WAIT_1 狀態。而當對方回應ACK報文后,則進入到FIN_WAIT_2 狀態。當然在實際的正常情況下,無論對方處于任何種情況下,都應該馬上回應ACK報文,所以FIN_WAIT_1 狀態一般是比較難見到的,而FIN_WAIT_2 狀態有時仍可以用netstat看到。
  • FIN_WAIT_2 :上面已經解釋了這種狀態的由來,實際上FIN_WAIT_2狀態下的SOCKET表示半連接,即有一方調用close()主動要求關閉連接。注意:FIN_WAIT_2 是沒有超時的(不像TIME_WAIT 狀態),這種狀態下如果對方不關閉(不配合完成4次揮手過程),那這個 FIN_WAIT_2 狀態將一直保持到系統重啟,越來越多的FIN_WAIT_2 狀態會導致內核crash。
  • TIME_WAIT :表示收到了對方的FIN報文,并發送出了ACK報文。 TIME_WAIT狀態下的TCP連接會等待2*MSL(Max Segment Lifetime,最大分段生存期,指一個TCP報文在Internet上的最長生存時間。)在Linux可以通過cat /proc/sys/net/ipv4/tcp_fin_timeout看到本機的這個值,然后即可回到CLOSED 可用狀態了。
  • CLOSING :這種狀態在實際情況中應該很少見,屬于一種比較罕見的例外狀態。正常情況下,當一方發送FIN報文后,按理來說是應該先收到(或同時收到)對方的ACK報文,再收到對方的FIN報文。但是CLOSING 狀態表示一方發送FIN報文后,并沒有收到對方的ACK報文,反而卻也收到了對方的FIN報文。什么情況下會出現此種情況呢?那就是當雙方幾乎在同時close()一個SOCKET的話,就出現了雙方同時發送FIN報文的情況,這是就會出現CLOSING 狀態,表示雙方都正在關閉SOCKET連接。
  • CLOSE_WAIT :表示正在等待關閉。怎么理解呢?當對方close()一個SOCKET后發送FIN報文給自己,你的系統毫無疑問地將會回應一個ACK報文給對方,此時TCP連接則進入到CLOSE_WAIT狀態。接下來呢,你需要檢查自己是否還有數據要發送給對方,如果沒有的話,那你也就可以close()這個SOCKET并發送FIN報文給對方,即關閉自己到對方這個方向的連接。有數據的話則看程序的策略,繼續發送或丟棄。簡單地說,當你處于CLOSE_WAIT 狀態下,需要完成的事情是等待你去關閉連接。
  • LAST_ACK :當被動關閉的一方在發送FIN報文后,等待對方的ACK報文的時候,就處于LAST_ACK 狀態。當收到對方的ACK報文后,也就可以進入到CLOSED 可用狀態了。

二、狀態的監控方法

前文已經有提及,可以通過netstat命令查看TCP連接的狀態。圖2是一個簡單的例子,執行該命令的時候不帶任何參數。

圖2 netstat執行結果

由上圖可以看出,通過netstat可以看到每個TCP連接和UDP的狀態和詳細的IP地址等信息。該命令有很多參數,通過不同的參數可以得到我們想要的內容。下面我們舉幾個具體的例子。

1. 顯示所有端口信息

可以通過-a參數列出所有端口信息,而且可以附帶-t只列出TCP協議的,或者-u只列出UDP協議的端口信息。

?
  • [root@itworld123~]#?netstat?-a?#?列出所有端口?
  • [root@itworld123~]#?netstat?-at?#?列出所有TCP端口?
  • [root@itworld123~]#?netstat?-au?#?列出所有UDP端口?
  • 2. 顯示所有監聽狀態的套接字

    可以通過-l參數列出所有處于監聽狀態的套接字。當然也可以結合-t或者-u參數獲取想要的信息。如下是獲取TCP處于監聽狀態的套接字列表:

    ?
  • root@itworld123:~#?netstat?-lu?
  • ?

    圖3 監聽狀態列表

    3. 查看服務狀態

    可以查看具體的服務的監聽和套接字等狀態。例如下面命令用于查看ssh服務的狀態:

    ?
  • root@itworld123:~#netstat?-antp?|?grep?ssh?
  • 圖3 SSH狀態結果

    4. 其它

    當然,也可以通過shell腳本實現復雜的查詢,比如下面用于統計ESTABLISHED狀態的數量。

    ?
  • netstat?-n?|?awk?'/^tcp/?{++S[$NF]}?END?{for(a?in?S)?print?a,?S[a]}'?
  • netstat命令功能非常強大,由于篇幅問題,本文只能拋磚引玉,更多功能可以man一下看看,這里就不過多解釋。

    三、實際生產環境的意義

    前面啰嗦了一大堆,我們回到正題,了解這些狀態到底有什么用呢?我們知道Linux操作系統對文件句柄的總量是有限制的,套接字也屬于文件句柄,因此也是有限制的。了解套接字的狀態有助于我們了解服務器是否有隱患或者性能瓶頸。

    說到這,可能有的同學還是不明白,我們舉個簡單的例子。假設一臺服務器最多有6萬個句柄,如果由于某種業務場景,在服務器端出現大量的TIME_WAIT,此時這些套接字是無法馬上釋放,也就是無法馬上被重復使用,但仍然占用6萬句柄的名額。這塊,隨著時間的推移,可能會耗盡所有句柄,從而導致有新的連接請求是服務器端無法響應的問題。

    為了讓大家更形象的理解這些狀態在實際生產中的意義,我們舉幾個實際生產中遇到問題的例子。

    1. 服務器端大量TIME_WAIT

    (1) 現象描述

    某對象存儲服務,在監控系統發現有大量的TIME_WAIT。經確認該服務器是一臺新上架接入的服務器。經反復確認,具備相同功能的同集群的其它服務器工作都正常,并不存在大量TIME_WAIT的情況。

    (2) 問題分析

    結合協議我們知道主動關閉方會處于該狀態,而且TIME_WAIT狀態下的TCP連接會等待2*MSL。因此我們查看系統配置cat /proc/sys/net/ipv4/tcp_fin_timeout,發現是默認值。因此,確定是等待時間太長,導致套接字無法被利用所致。

    (3) 問題解決

    通過調整內核參數解決,打開文件/etc/sysctl.conf,編輯文件,加入以下內容:

    ?
  • net.ipv4.tcp_syncookies?=?1?
  • net.ipv4.tcp_tw_reuse?=?1?
  • net.ipv4.tcp_tw_recycle?=?1?
  • net.ipv4.tcp_fin_timeout?=?30?
  • 然后執行/sbin/sysctl -p讓參數生效。

    上述內容的含義具體如下:

    • net.ipv4.tcp_syncookies = 1表示開啟SYN Cookies。當出現SYN等待隊列溢出時,啟用cookies來處理,可防范少量SYN攻擊,默認為0,表示關閉;
    • net.ipv4.tcp_tw_reuse = 1表示開啟重用。允許將TIME-WAIT sockets重新用于新的TCP連接,默認為0,表示關閉;
    • net.ipv4.tcp_tw_recycle = 1表示開啟TCP連接中TIME-WAIT sockets的快速回收,默認為0,表示關閉。
    • net.ipv4.tcp_fin_timeout修改系統默認的TIMEOUT時間

    2. 服務器端大量ESTABLISHED

    (1) 問題描述

    某Tomcat服務器出現大量ESTABLISHED連接。

    (2) 問題分析

    根據協議狀態轉換情況,初步推斷是tomcat服務器回收session時出了問題,這個一般都跟服務器的Timeout設置有聯系。

    查看tomcat的配置文件 server.xml

    ?
  • <Connector?port="8080"?protocol="HTTP/1.1"?
  • ?connectionTimeout="20000"?
  • ?redirectPort="8443"?URIEncoding="UTF-8"?/>?
  • *****?
  • 我們重點關注一下connectionTimeout,這個配置導致建立一個socket連接后,如果一直沒有收到客戶端的FIN,也沒有數據過來,那么此連接也必須等到10s后,才能被超時釋放。由于服務器并發量大,而該超時時間有長,導致連接釋放嚴重滯后,因此出現大量的ESTABLISHED連接。

    (3) 問題解決

    分析上述問題后,我們有針對性的作出如下修改。

    ?
  • connectionTimeout="20000"?改為?connectionTimeout="100"?
  • acceptCount="100"改為acceptCount="5000"?
  • 修改后問題解決。

    實際的例子還很多,但萬變不離其宗,需要我們熟悉TCP協議和狀態轉換,這樣在實際生產中遇到問題就可以有理有據的進行分析,然后輕松解決。

    創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

    總結

    以上是生活随笔為你收集整理的TCP的状态转换及生产问题实操的全部內容,希望文章能夠幫你解決所遇到的問題。

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