學(xué)習(xí)筆記:TCP協(xié)議3次握手4次揮手

TCP協(xié)議結(jié)構(gòu)

TCP協(xié)議結(jié)構(gòu)

里面主要部分是包序號(hào)和確認(rèn)序號(hào)乒省,包序號(hào)是為了解決亂序的問題巧颈,知道那個(gè)包在前,哪個(gè)包在后袖扛。確認(rèn)序號(hào)砸泛,發(fā)出去的包要有個(gè)確認(rèn),如果沒有收到就要重新發(fā)送蛆封。
狀態(tài)位

  • SYN:發(fā)起一個(gè)連接
  • ACK:回復(fù)
  • RST: 重新連接
  • FIN:結(jié)束連接
    窗口大小唇礁,TCP要做流量控制,通信雙方各聲明一個(gè)窗口惨篱,標(biāo)識(shí)自己的處理能力盏筐,讓對(duì)端別發(fā)送太快,撐死我砸讳,也別發(fā)送太慢琢融,餓死我

TCP的3次握手

3次握手流程

TCP建立連接時(shí)的3次握手也常稱為“請(qǐng)求->應(yīng)答->應(yīng)答之應(yīng)答”。為什么是3次呢簿寂,因?yàn)榻ㄟB接的雙方都要做一個(gè)發(fā)送和收到確認(rèn)才能證明雙方連接建立了漾抬。
3次握手除了建立連接之外,還為了溝通意見事情常遂,就是TCP包序號(hào)的問題纳令,這也是SYN的由來,全稱Synchronize Sequence Number。雙方要確定一個(gè)起始的序號(hào)平绩,序號(hào)不能每次都從1開始圈匆,因?yàn)閺?開始如果掉線又重連,上次的包可能還在路上捏雌,那序號(hào)就重復(fù)了跃赚。所以每個(gè)連接都要有個(gè)不同的起始序號(hào)。這個(gè)起始序號(hào)是隨著時(shí)間變化的腹忽,可以看作一個(gè)32位的計(jì)數(shù)器来累,每4ms加1砚作,這樣到兩個(gè)包重復(fù)窘奏,需要4個(gè)小時(shí),早就超過上一個(gè)的生存時(shí)間了(TTL)葫录。
Sequence Number如何增加
sequence number不是每次加1的着裹,而是和傳輸?shù)淖止?jié)數(shù)有關(guān)。如果雙方3次握手后seq都是1米同,這時(shí)候A給B發(fā)了一個(gè)長度1440的包骇扇,那seq就變成1440,。B給1440的ACK回1441面粮,證明1440收到了少孝。
狀態(tài)演變
Server端監(jiān)聽某個(gè)端口,處于LISTEN狀態(tài)熬苍∩宰撸客戶端主動(dòng)發(fā)起連接發(fā)送SYN,之后處于SYN-SENT狀態(tài)柴底。服務(wù)端收到SYN之后婿脸,向客戶端發(fā)送SYN和ACK,之后服務(wù)端處于SYN-RCVD狀態(tài)柄驻『鳎客戶端收到服務(wù)端的反饋后再發(fā)送ACK,之后客戶端處于ESTABLISHED狀態(tài)鸿脓,服務(wù)端收到后抑钟,也處于ESTABLISHED狀態(tài)。
這里有一個(gè)問題野哭,如果client發(fā)送SYN之后掉線了在塔,服務(wù)端發(fā)送SYN-ACK后會(huì)一直保持住資源,等待客戶端回來的ACK虐拓。如果沒收到心俗,就會(huì)重試SYN-ACK,默認(rèn)重試5次,間隔從1s開始城榛,每次翻倍揪利。所以,總共需要1s + 2s + 4s+ 8s+ 16s + 32s = 2^6 -1 = 63s狠持,Server端才會(huì)結(jié)束疟位,釋放資源。
SYN flood攻擊
client利用server端會(huì)等待的特性(63s),不斷給server發(fā)SYN喘垂,發(fā)完就下線甜刻,把服務(wù)端的SYN隊(duì)列耗盡,讓正常的鏈接請(qǐng)求不能處理正勒。linux處理這個(gè)的方法是設(shè)置tcp_syncookies參數(shù)得院,當(dāng)SYN隊(duì)列滿了以后,TCP發(fā)SYN-ACK的時(shí)候會(huì)帶上cookie章贞,然后正常的client再ACK的時(shí)候帶上就可以建立鏈接祥绞,但是這種方式不是常規(guī)用法。更通用的方法是調(diào)整幾個(gè)參數(shù)鸭限,第一個(gè)是tcp_synack_retries,用來減少Server端SYN-ACK重試次數(shù)蜕径;第二個(gè)是tcp_max_syn_backlog,增大隊(duì)列長度败京;第三個(gè)是tcp_abort_on_overflow兜喻,處理不過來干脆拒絕連接。

TCP的四次揮手

一方發(fā)起關(guān)閉請(qǐng)求

四次揮手流程

發(fā)起端(A)想斷開連接的時(shí)候赡麦,發(fā)送FIN朴皆,然后進(jìn)入FIN_WAIT_1的狀態(tài)。接收端(B)收到后隧甚,發(fā)送ACK车荔,表示自己知道了,進(jìn)入CLOSE_WAIT狀態(tài)戚扳。
A收到B的確認(rèn)后進(jìn)入FIN_WAIT_2的狀態(tài)忧便,如果這個(gè)時(shí)候B跑路,A將永遠(yuǎn)處于這個(gè)狀態(tài)帽借。linux針對(duì)這種情況珠增,支持tcp_fin_timeout參數(shù),超時(shí)后A就算B跑路了砍艾。
如果B沒跑路蒂教,會(huì)再發(fā)FIN和ACK,表示我也不玩了脆荷,然后B進(jìn)入LAST-ACK狀態(tài)凝垛。A收到后回復(fù)ACK懊悯,進(jìn)入TIME-WAIT狀態(tài)。而B收到A的ACK后進(jìn)入CLOSED狀態(tài)梦皮。A等待一段時(shí)間也會(huì)進(jìn)入CLOSE就徹底結(jié)束了炭分。
A為什么要等一段時(shí)間呢,一是為了防止A最后的ACK B沒收到剑肯,B會(huì)要求重發(fā)捧毛,如果A直接CLOSE,就不會(huì)重發(fā)了。二是B在發(fā)送最后的FIN和ACK之前的數(shù)據(jù)包可能比這兩個(gè)包晚到让网。所以A要等一段再關(guān)閉呀忧。
A的TIME_WAIT的時(shí)間是2個(gè)MSL(Max Segment Lifetime)報(bào)文最大生存時(shí)間。
還有一種情況是B一直沒收到最后的ACK溃睹,于是要求重發(fā)而账,而A已經(jīng)過了2MSL了,A會(huì)回一個(gè)RST表示自己跑路了丸凭。

雙方都發(fā)起斷鏈請(qǐng)求

兩端同時(shí)斷鏈接

因?yàn)門CP是全雙工的福扬,所以,發(fā)送方和接收方都需要Fin和Ack惜犀。只不過,有一方是被動(dòng)的狠裹,所以看上去就成了所謂的4次揮手虽界。如果兩邊同時(shí)斷連接,那就會(huì)就進(jìn)入到CLOSING狀態(tài)涛菠,然后到達(dá)TIME_WAIT狀態(tài)莉御。

TCP狀態(tài)機(jī)

TCP狀態(tài)機(jī)

擴(kuò)展問題思考

日常維護(hù)中查看服務(wù)器所有連接的狀態(tài)

$netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
#結(jié)果實(shí)例
TIME_WAIT 814
CLOSE_WAIT 1
FIN_WAIT1 1
ESTABLISHED 634
SYN_RECV 2
LAST_ACK 1

如果web服務(wù)器連接出異常,百分之八九十都是下面兩種情況:

  • 服務(wù)器保持了大量TIME_WAIT狀態(tài)
  • 服務(wù)器保持了大量CLOSE_WAIT狀態(tài)
    這個(gè)時(shí)候新的請(qǐng)求就無法被處理了俗冻,接著就是大量Too Many Open Files異常
    服務(wù)器保持了大量TIME_WAIT怎么解決
    這個(gè)是服務(wù)器主動(dòng)發(fā)起關(guān)閉連接引起礁叔,所以要調(diào)整的是本端服務(wù)器的參數(shù),修改/etc/sysctl.conf
#對(duì)于一個(gè)新建連接迄薄,內(nèi)核要發(fā)送多少個(gè) SYN 連接請(qǐng)求才決定放棄,不應(yīng)該大于255琅关,默認(rèn)值是5,對(duì)應(yīng)于180秒左右時(shí)間   
net.ipv4.tcp_syn_retries=2  
#net.ipv4.tcp_synack_retries=2  
#表示當(dāng)keepalive起用的時(shí)候讥蔽,TCP發(fā)送keepalive消息的頻度涣易。缺省是2小時(shí),改為300秒  
net.ipv4.tcp_keepalive_time=1200  
net.ipv4.tcp_orphan_retries=3  
#表示如果套接字由本端要求關(guān)閉冶伞,這個(gè)參數(shù)決定了它保持在FIN-WAIT-2狀態(tài)的時(shí)間  
net.ipv4.tcp_fin_timeout=30    
#表示SYN隊(duì)列的長度新症,默認(rèn)為1024,加大隊(duì)列長度為8192响禽,可以容納更多等待連接的網(wǎng)絡(luò)連接數(shù)徒爹。  
net.ipv4.tcp_max_syn_backlog = 4096  
#表示開啟SYN Cookies荚醒。當(dāng)出現(xiàn)SYN等待隊(duì)列溢出時(shí),啟用cookies來處理隆嗅,可防范少量SYN攻擊腌且,默認(rèn)為0,表示關(guān)閉  
net.ipv4.tcp_syncookies = 1  
  
#表示開啟重用榛瓮。允許將TIME-WAIT sockets重新用于新的TCP連接铺董,默認(rèn)為0,表示關(guān)閉  
net.ipv4.tcp_tw_reuse = 1  
#表示開啟TCP連接中TIME-WAIT sockets的快速回收禀晓,默認(rèn)為0精续,表示關(guān)閉  
net.ipv4.tcp_tw_recycle = 1  
  
##減少超時(shí)前的探測次數(shù)   
net.ipv4.tcp_keepalive_probes=5   
##優(yōu)化網(wǎng)絡(luò)設(shè)備接收隊(duì)列   
net.core.netdev_max_backlog=3000 

這里頭主要注意到的是net.ipv4.tcp_tw_reuse
net.ipv4.tcp_tw_recycle
net.ipv4.tcp_fin_timeout
net.ipv4.tcp_keepalive_*
這幾個(gè)參數(shù)。

net.ipv4.tcp_tw_reuse和net.ipv4.tcp_tw_recycle的開啟都是為了回收處于TIME_WAIT狀態(tài)的資源粹懒。
net.ipv4.tcp_fin_timeout這個(gè)時(shí)間可以減少在異常情況下服務(wù)器從FIN-WAIT-2轉(zhuǎn)到TIME_WAIT的時(shí)間重付。
net.ipv4.tcp_keepalive_*一系列參數(shù),是用來設(shè)置服務(wù)器檢測連接存活的相關(guān)配置凫乖。
注意tcp_tw_reuse确垫,tcp_tw_recycle開啟的風(fēng)險(xiǎn),用這個(gè)是非常危險(xiǎn)的:http://blog.csdn.net/wireless_tech/article/details/6405755
所以設(shè)置keepAlive是非常重要的帽芽。

服務(wù)器保持了大量TIME_WAIT怎么解決
如果一直保持在CLOSE_WAIT狀態(tài)删掀,那么只有一種情況,就是在對(duì)方關(guān)閉連接之后服務(wù)器程序自己沒有進(jìn)一步發(fā)出ack信號(hào)导街。換句話說披泪,就是在對(duì)方連接關(guān)閉之后,程序里沒有檢測到搬瑰,或者程序壓根就忘記了這個(gè)時(shí)候需要關(guān)閉連接款票,于是這個(gè)資源就一直被程序占著。

如果你使用的是HttpClient并且你遇到了大量CLOSE_WAIT的情況泽论,那么這篇日志也許對(duì)你有用:http://blog.csdn.net/shootyou/article/details/6615051

在那邊日志里頭我舉了個(gè)場景艾少,來說明CLOSE_WAIT和TIME_WAIT的區(qū)別,這里重新描述一下:

服務(wù)器A是一臺(tái)爬蟲服務(wù)器翼悴,它使用簡單的HttpClient去請(qǐng)求資源服務(wù)器B上面的apache獲取文件資源缚够,正常情況下,如果請(qǐng)求成功抄瓦,那么在抓取完資源后潮瓶,服務(wù)器A會(huì)主動(dòng)發(fā)出關(guān)閉連接的請(qǐng)求,這個(gè)時(shí)候就是主動(dòng)關(guān)閉連接钙姊,服務(wù)器A的連接狀態(tài)我們可以看到是TIME_WAIT毯辅。如果一旦發(fā)生異常呢?假設(shè)請(qǐng)求的資源服務(wù)器B上并不存在煞额,那么這個(gè)時(shí)候就會(huì)由服務(wù)器B發(fā)出關(guān)閉連接的請(qǐng)求思恐,服務(wù)器A就是被動(dòng)的關(guān)閉了連接沾谜,如果服務(wù)器A被動(dòng)關(guān)閉連接之后程序員忘了讓HttpClient釋放連接,那就會(huì)造成CLOSE_WAIT的狀態(tài)了胀莹。

所以如果將大量CLOSE_WAIT的解決辦法總結(jié)為一句話那就是:查代碼基跑。因?yàn)閱栴}出在服務(wù)器程序里頭啊。

參考文章:
[極客時(shí)間] 趣談網(wǎng)絡(luò)協(xié)議 --劉超
[CSDN] 再談應(yīng)用環(huán)境下的TIME_WAIT和CLOSE_WAIT

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末描焰,一起剝皮案震驚了整個(gè)濱河市媳否,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌荆秦,老刑警劉巖篱竭,帶你破解...
    沈念sama閱讀 218,386評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異步绸,居然都是意外死亡掺逼,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門瓤介,熙熙樓的掌柜王于貴愁眉苦臉地迎上來吕喘,“玉大人,你說我怎么就攤上這事刑桑÷戎剩” “怎么了?”我有些...
    開封第一講書人閱讀 164,704評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵漾月,是天一觀的道長病梢。 經(jīng)常有香客問我,道長梁肿,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,702評(píng)論 1 294
  • 正文 為了忘掉前任觅彰,我火速辦了婚禮吩蔑,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘填抬。我一直安慰自己烛芬,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,716評(píng)論 6 392
  • 文/花漫 我一把揭開白布飒责。 她就那樣靜靜地躺著赘娄,像睡著了一般。 火紅的嫁衣襯著肌膚如雪宏蛉。 梳的紋絲不亂的頭發(fā)上遣臼,一...
    開封第一講書人閱讀 51,573評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音拾并,去河邊找鬼揍堰。 笑死鹏浅,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的屏歹。 我是一名探鬼主播隐砸,決...
    沈念sama閱讀 40,314評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼蝙眶!你這毒婦竟也來了季希?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,230評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤幽纷,失蹤者是張志新(化名)和其女友劉穎式塌,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體霹崎,經(jīng)...
    沈念sama閱讀 45,680評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡珊搀,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,873評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了尾菇。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片境析。...
    茶點(diǎn)故事閱讀 39,991評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖派诬,靈堂內(nèi)的尸體忽然破棺而出劳淆,到底是詐尸還是另有隱情,我是刑警寧澤默赂,帶...
    沈念sama閱讀 35,706評(píng)論 5 346
  • 正文 年R本政府宣布沛鸵,位于F島的核電站,受9級(jí)特大地震影響缆八,放射性物質(zhì)發(fā)生泄漏曲掰。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,329評(píng)論 3 330
  • 文/蒙蒙 一奈辰、第九天 我趴在偏房一處隱蔽的房頂上張望栏妖。 院中可真熱鬧,春花似錦奖恰、人聲如沸吊趾。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽论泛。三九已至,卻和暖如春蛹屿,著一層夾襖步出監(jiān)牢的瞬間屁奏,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評(píng)論 1 270
  • 我被黑心中介騙來泰國打工蜡峰, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留了袁,地道東北人朗恳。 一個(gè)月前我還...
    沈念sama閱讀 48,158評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像载绿,于是被迫代替她去往敵國和親粥诫。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,941評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容