<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          TCP 連接的前世今生

          共 9273字,需瀏覽 19分鐘

           ·

          2021-06-08 09:25

          點(diǎn)擊上方“碼農(nóng)突圍”,馬上關(guān)注
          這里是碼農(nóng)充電第一站,回復(fù)“666”,獲取一份專屬大禮包
          真愛,請?jiān)O(shè)置“星標(biāo)”或點(diǎn)個(gè)“在看

          前言

          大家好!我是盼盼!
          之前寫了幾篇關(guān)于算法和 linux 命令的文章,今天來學(xué)習(xí)下,網(wǎng)絡(luò)協(xié)議相關(guān)的知識(shí)。不管你是客戶端,還是服務(wù)端開發(fā),網(wǎng)絡(luò)協(xié)議這塊都是要學(xué)習(xí)和了解的。
          工作和面試中,網(wǎng)絡(luò)協(xié)議都會(huì)用到。雖然學(xué)習(xí)網(wǎng)絡(luò)對(duì)編碼沒有實(shí)質(zhì)的幫助,但對(duì)你處理一下網(wǎng)絡(luò)連接問題,幫助大大的。下面來一起學(xué)習(xí)下,發(fā)車!

          緣起

          在世界上各地,各種各樣的電腦,運(yùn)行著各自不同的操作系統(tǒng)為大家服務(wù)。這些電腦,在表達(dá)同一種信息的時(shí)候,所使用的方法是千差萬別。
          計(jì)算機(jī)使用者意識(shí)到,計(jì)算機(jī)只是單兵作戰(zhàn),并不會(huì)發(fā)揮太大的作用。只有把它們聯(lián)合起來,電腦才會(huì)發(fā)揮出它最大的潛力。
          于是人們就想方設(shè)法的,用電線把電腦連接到了一起。但是簡單的連到一起是遠(yuǎn)遠(yuǎn)不夠的,就好像語言不同的兩個(gè)人互相見了面,完全不能交流信息。因而他們需要定義一些共通的東西來進(jìn)行交流,TCP/IP 就是為此而生。
          TCP/IP 不是一個(gè)協(xié)議,而是一個(gè)協(xié)議族的統(tǒng)稱。里面包括了 IP 協(xié)議,IMCP 協(xié)議,TCP 協(xié)議,以及我們更加熟悉的 http、ftp 協(xié)議等等。電腦有了這些,就好像學(xué)會(huì)了外語一樣,就可以和其他的計(jì)算機(jī)終端做自由的交流了。今天我們學(xué)習(xí) TCP 協(xié)議。

          什么是TCP

          TCP(傳輸控制協(xié)議)是一種面向連接的、可靠的、基于字節(jié)流的傳輸層通信協(xié)議,它完成第四層傳輸層所指定的功能,網(wǎng)絡(luò)模型下面介紹。
          TCP 協(xié)議的特點(diǎn)是:

          • 面向連接:一定是「一對(duì)一」才能連接,不能像 UDP 協(xié)議可以一個(gè)主機(jī)同時(shí)向多個(gè)主機(jī)發(fā)送消息,也就是一對(duì)多是無法做到的。
          • 可靠交付:無論的網(wǎng)絡(luò)鏈路中出現(xiàn)了怎樣的鏈路變化,TCP 都可以保證一個(gè)報(bào)文一定能夠到達(dá)接收端。
          • 面向字節(jié)流:也就是說僅僅把上層協(xié)議傳遞過來的數(shù)據(jù)當(dāng)成字節(jié)傳輸。

          網(wǎng)絡(luò)模型

          七層模型

          國際標(biāo)準(zhǔn)化組織 ISO ,在1981 年正式推薦了一個(gè)網(wǎng)絡(luò)系統(tǒng)結(jié)構(gòu)一七層參考模型,也叫作開放系統(tǒng)互連模。由于這個(gè)標(biāo)準(zhǔn)模型的建立,使得各種計(jì)算機(jī)網(wǎng)絡(luò)均向它靠攏,大大推動(dòng)了網(wǎng)絡(luò)通信的發(fā)展。
          這個(gè) ISO 層網(wǎng)絡(luò)模型各層的名字、主要功能對(duì)應(yīng)的典型設(shè)備和傳輸單位如下圖:
          這個(gè)七層網(wǎng)絡(luò)模型在數(shù)據(jù)的傳輸過程中還會(huì)對(duì)數(shù)據(jù)進(jìn)行封裝,如下圖:
          ISO 層網(wǎng)絡(luò)模型中,當(dāng)一臺(tái)主需要傳送用戶的數(shù)據(jù) (data) 時(shí),數(shù)據(jù)首先通過應(yīng)用層的接口進(jìn)入應(yīng)用層。
          先看幾個(gè)常見報(bào)頭術(shù)語簡寫:
          • 應(yīng)用層報(bào)頭:Ppplication Header, 簡稱 AH
          • 表示層報(bào)頭:Presentation Header, 簡稱 PH
          • 會(huì)話層報(bào)頭:Session Header, 簡稱 SH
          • 傳輸層報(bào)頭:Transport Header, 簡稱 TH
          • 網(wǎng)絡(luò)層報(bào)頭:Network Header, 簡稱 NH
          • 數(shù)據(jù)鏈路層報(bào)頭:Data link Header, 簡稱 DH
          • 應(yīng)用層協(xié)議數(shù)據(jù)單元:Protocol Data Unit,簡稱 PDU
          • 數(shù)據(jù)鏈路層報(bào)尾:Data link Termination,簡稱 DT
          在應(yīng)用層,用戶的數(shù)據(jù)被加上應(yīng)用層的報(bào)頭 AH,形成應(yīng)用層協(xié)議數(shù)據(jù)單元 PDU,然后被遞交到下層表示層。
          表示層并不關(guān)心上層應(yīng)用層的數(shù)據(jù)格式,而是把整個(gè)應(yīng)用層遞交的數(shù)據(jù)包,看成是一個(gè)整體進(jìn)行封裝,即加上表示層的報(bào)頭 PH。然后,遞交到下層會(huì)話層。
          同樣,會(huì)話層、傳輸層、網(wǎng)絡(luò)層(假設(shè)用 TCP 傳輸,則是 TCP 數(shù)據(jù)+ IP 包頭)、數(shù)據(jù)鏈路層(把上層的 TCP 數(shù)據(jù)+ IP 頭統(tǒng)一稱為幀數(shù)據(jù),即幀 +幀數(shù)據(jù)+幀尾(CRC)也都要分別給上層遞交下來的數(shù)據(jù)加上自己的報(bào)頭)。
          它們是:會(huì)話層報(bào)頭 SH、傳輸層報(bào)頭 TH、網(wǎng)絡(luò)層報(bào)頭 NH 和數(shù)據(jù)鏈路層報(bào)頭DH。其中,數(shù)據(jù)鏈路層還要給網(wǎng)絡(luò)層遞交的數(shù)據(jù)加上數(shù)據(jù)鏈路層報(bào)尾形成最終的一幀數(shù)據(jù)。
          當(dāng)一幀數(shù)據(jù),通過物理層傳送到目標(biāo)主機(jī)的物理層時(shí),該主機(jī)的物理層把它遞交到上層一一數(shù)據(jù)鏈路層。數(shù)據(jù)鏈路層負(fù)責(zé)去掉數(shù)據(jù)幀的幀頭部和尾部(同時(shí)還進(jìn)行數(shù)據(jù)校驗(yàn))。如果數(shù)據(jù)沒有出錯(cuò),則遞交到上層網(wǎng)絡(luò)層。
          同樣,網(wǎng)絡(luò)層、傳輸層、會(huì)話層、表示層、應(yīng)用層也要做類似的工作。最終 ,原始數(shù)據(jù)被遞交到目標(biāo)主機(jī)的具體應(yīng)用程序中。

          五層網(wǎng)絡(luò)模型

          五層模型的網(wǎng)絡(luò)體系也經(jīng)常被提到,這五層的名字與功能分別如下所述:
          • 應(yīng)用層:確定進(jìn)程之間通信的性質(zhì),以滿足用戶需求。應(yīng)用層協(xié)議有很多。如支持萬維網(wǎng)應(yīng)用的 HTTP 協(xié)議、支持電子郵件的 SMTP 協(xié)議、等等。
          • 傳輸層:負(fù)責(zé)主機(jī)間不同進(jìn)程的通信。這一層中的協(xié)議有面向連接的 TCP (傳輸控制協(xié)議)、無連接的 UDP (用戶數(shù)據(jù)報(bào)協(xié)議);數(shù)據(jù)傳輸?shù)膯挝环Q為報(bào)文段或用戶數(shù)據(jù)報(bào)。
          • 網(wǎng)絡(luò)層:負(fù)責(zé)分組交換網(wǎng)中不同主機(jī)間的通信。作用為:發(fā)送數(shù)據(jù)時(shí),將運(yùn)輸層中的報(bào)文段或用戶數(shù)據(jù)報(bào)封裝成 IP 數(shù)據(jù)報(bào),并選擇合適路由。
          • 數(shù)據(jù)鏈路層:負(fù)責(zé)將網(wǎng)絡(luò)層的 IP 數(shù)據(jù)報(bào)組裝成幀。
          • 物理層 :透明地傳輸比特流。

          四層網(wǎng)絡(luò)模型

          前面的兩種模型都是學(xué)術(shù)上的概念,使用并不廣泛 還有一個(gè)四層模型,使用最為廣泛一 TCP/IP 分層模型。幾種模型如下圖:
          TCP/IP 分層的四模型的個(gè)協(xié)議層分別完成以下的功能:
          • 網(wǎng)絡(luò)接口層:包括用于協(xié)作 IP 數(shù)據(jù),在已有網(wǎng)絡(luò)介質(zhì)上傳輸?shù)膮f(xié)議。實(shí)際上 TCP/IP 標(biāo)準(zhǔn)并不定義與 ISO 數(shù)據(jù)鏈路層和物理層相對(duì)應(yīng)的功能 。相反,它定義了像 ARP (地址解析協(xié)議)這樣的協(xié)議,提供 TCP/IP 協(xié)議的數(shù)據(jù)結(jié)構(gòu)和實(shí)際物理硬件之間的接口。
          • 網(wǎng)絡(luò)層:網(wǎng)絡(luò)層對(duì)應(yīng)于 OSI 七層參考模型的網(wǎng)絡(luò)層。本層包含 IP 協(xié)議、RIP 協(xié)議(路由信息協(xié)議),負(fù)責(zé)數(shù)據(jù)的包裝、尋址和路由。同時(shí)還包含 ICMP (網(wǎng)間控制報(bào)文協(xié)議)用來提供網(wǎng)絡(luò)診斷信息。
          • 傳輸層:傳輸層對(duì)應(yīng)于 OSI 七層參考模型的傳輸層,它提供兩種端到端的通信服務(wù)。其中 TCP協(xié)議提供可靠的數(shù)據(jù)流運(yùn)輸服務(wù), UDP 協(xié)議提供不可靠的用戶數(shù)據(jù)報(bào)服務(wù)。
          • 應(yīng)用層:應(yīng)用層對(duì)應(yīng)于 OSI 七層參考模型的應(yīng)用層和表示層。因特網(wǎng)的應(yīng)用層協(xié)議包括  FTP (文件傳輸協(xié)議)HTTP (超文本傳輸協(xié)議)、 Telent (遠(yuǎn)程終端協(xié)議)、SMTP (簡單郵件傳送協(xié)議)、 IRC (因特網(wǎng)中繼會(huì)話)、NNTP (網(wǎng)絡(luò)新聞傳輸協(xié)議)等。
          綜上所述,我們需要知道 TCP 協(xié)議在網(wǎng)絡(luò) OSI 的七層模型中的第四層傳輸層, IP 協(xié)議在第三層網(wǎng)絡(luò)層, ARP 協(xié)議在第二層數(shù)據(jù)鏈路層;在第二層上的數(shù)據(jù)叫 Frame ,在第三層上的數(shù)據(jù)叫 Packet ,第四層的數(shù)據(jù)叫 Segment 所有程序的數(shù)據(jù)首先會(huì)打包到 TCP 的 Segment 中。
          然后 TCP 的 Segment 會(huì)打包到 IP 的 Packet ,然后再打包到以太網(wǎng) Ethernet 的 Frame 中,傳到對(duì)端后,各個(gè) 解析自己的協(xié)議,然后把數(shù)據(jù)交給更高層的協(xié)議處理。

          TCP頭格式

          在學(xué)習(xí) TCP 連接之前,還要學(xué)習(xí)一下 TCP 頭部格式。因?yàn)?TCP 連接建立,需要用 TCP 包來交換和管理數(shù)據(jù),下面看一下 TCP 頭部格式。
          TCP 頭部里每個(gè)字段都為管理 TCP 連接和控制數(shù)據(jù)流起了重要作用。
          16 位端口號(hào):告知主機(jī)該報(bào)文段是來自哪里(源端口)以及傳給哪個(gè)上層協(xié)議或應(yīng)用程序(目的端口)的。
          進(jìn)行 TCP 通信時(shí),客戶端通常使用系統(tǒng)自動(dòng)選擇的臨時(shí)端口號(hào),而服務(wù)器則使用知名服務(wù)端口號(hào)。所有知名服務(wù)使用的端口號(hào)都定義在  /etc/services 文件中。
          32 位序號(hào)(sequence number):一次 TCP 通信(從 TCP 連接建立到斷開)過程中個(gè)傳輸方向上的字節(jié)流的每個(gè)字節(jié)的編號(hào)。
          32 位確認(rèn)號(hào)(acknowledgement number):用作對(duì)另一方發(fā)送來的 TCP 報(bào)文段的響應(yīng)其值是收到的 TCP 報(bào)文段的序號(hào)值加 1。
          4 位頭部長度(header length):標(biāo)識(shí)該 TCP 頭部有多少個(gè) 32bit ( 4 Byte 因?yàn)樽畲竽鼙硎?15 ,所以 TCP 頭部最長是 60 Byte。
          6 位標(biāo)志位包含如下幾項(xiàng):
          • URG 標(biāo)志,表示緊急指針是否有效。
          • ACK 標(biāo)志,表示確認(rèn)號(hào)是否有效,一般稱攜帶 ACK 標(biāo)志的 TCP 報(bào)文段為"確認(rèn)報(bào)文段"。
          • PSH 標(biāo)志,提示接收端應(yīng)用程序應(yīng)該立即從 TCP 接收緩沖區(qū)中讀走數(shù)據(jù),為接收后續(xù)數(shù)據(jù)騰出空間(如果應(yīng)用程序不將接收到的數(shù)據(jù)讀走,它們就會(huì)直停留在 TCP 接收緩沖區(qū)中)。
          • RST 標(biāo)志,表示要求對(duì)方重新建立連接,一般稱攜帶 RST 標(biāo)志的 TCP 報(bào)文段為"復(fù)位報(bào)文段"。
          • SYN 標(biāo)志,表示請求建立 個(gè)連接,一般稱攜帶 SYN 標(biāo)志的 TCP 報(bào)文段為"同步報(bào)文段"。FIN 標(biāo)志,表示通知對(duì)方本端要關(guān)閉連接了,一般稱攜帶 FIN 標(biāo)志的 TCP 報(bào)文段為"結(jié)束報(bào)文段"。
          16 位窗口大小(window size):是 TCP 流量控制的一個(gè)手段。這里說的窗口,指的是接收通告窗口( Receiver Window, RWND)。它告訴對(duì)方本端的 TCP 接收緩沖區(qū)還能容納多少字節(jié)的數(shù)據(jù),這樣對(duì)方就可以控制發(fā)送數(shù)據(jù)的速度。
          16 位校驗(yàn)和(TCP checksum):由發(fā)送端填充,接收端對(duì) TCP 報(bào)文段執(zhí)行 CRC 算法,以檢驗(yàn) TCP 報(bào)文段在傳輸過程中是否損壞 。注意,這個(gè)校驗(yàn)不僅包括 TCP 頭部,也包括數(shù)據(jù)部分。這也是 TCP 可靠傳輸?shù)囊粋€(gè)重要保障。
          16 位緊急指針(urgent pointer):是一個(gè)正的偏移量。它和序號(hào)字段的值相加表示最后一個(gè)緊急數(shù)據(jù)的下一字節(jié)的序號(hào) 。確切地說,這個(gè)字段是緊急指針相對(duì)當(dāng)前序號(hào)的偏移,不妨稱之為“緊急偏移”。TCP 的緊急指針是發(fā)送端向接收端發(fā)送緊急數(shù)據(jù)的方法。
          綜上,你需要注意如下幾點(diǎn):
          TCP 的包是沒有 IP 地址的,那是 IP 層上的事,但是有源端口和目的端口。
          一個(gè)TCP 連接需要四元組( src_ip,src_port,dst_ip,dst_port )來表示是同一個(gè)連接 準(zhǔn)確說是五元組,還有一個(gè)是協(xié)議 但因?yàn)檫@里只是強(qiáng)調(diào) TCP 協(xié)議,所以,只說四元組。
          Sequence Number 是包的序號(hào),用來解決網(wǎng)絡(luò)包亂序(reordering )問題。
          Acknowledgement Number 就是 ACK ,用于確認(rèn)收到,用來解決不丟包的問題。
          Window Advertised Window ,也就是著名 的滑動(dòng)窗口 Sliding Window ),用于解決流量控制問題。
          TCP Flag ,也就是包的類型,主要是用于操控 TCP 的狀態(tài)機(jī)的。

          TCP三次握手

          其實(shí),網(wǎng)絡(luò)上的傳輸是沒有連接的, TCP 是一樣的 TCP 所謂的 “連接”,其實(shí)只不過是在通信的雙方維護(hù)一個(gè)“連接狀態(tài)”,讓它看上去好像有連接一樣 所以, TCP 的狀態(tài)變換是非常重要的 。
          先來看一下著名的三次握手圖。
          TCP 連接的建立可以簡單地稱為三次握手,而連接的中止則可以稱為四次揮手。
          建立連接 TCP/IP 協(xié)議中, TCP 協(xié)議提供可靠的連接服務(wù),采用三次握手建立一個(gè)連接。
          • 第一次握手:建立連接時(shí),客戶端發(fā)送 SYN 包到服務(wù)器,并進(jìn)入 SYN_SEND 狀態(tài),等待服務(wù)器確認(rèn)。

          • 第二次握手:服務(wù)器收到 SYN 包,必須確認(rèn)客戶的 SYN ,同時(shí)自己也發(fā)送一個(gè) SYN 包,即 SYN+ACK 包,此時(shí)服務(wù)器進(jìn)入 SYN_RECV 狀態(tài)。

          • 第三次握手 :客戶端收到服務(wù)器的 SYN + ACK 包,向服務(wù)器發(fā)送確認(rèn)包 ACK,此包發(fā)送完畢,客戶端和服務(wù)器進(jìn)入 ESTABLISHE 態(tài)。

          完成 三次握手,客戶端與服務(wù)器開始傳送數(shù)據(jù),也就是 ESTABLISHED 狀態(tài)。

          連接建立中的異常

          建連接時(shí)SYN超時(shí)問題

          如果 server 端因?yàn)槟撤N情況沒有收到 client 回來的 ACK,那么,這個(gè)連接處還處于一個(gè)未建立的狀態(tài)。于是,server端如果在一定時(shí)間內(nèi)沒有收到,則 server 端的 TCP 會(huì)重發(fā) SYN_ACK。
          在Linux下,默認(rèn)重試次數(shù)為5次,重試的間隔時(shí)間從1s開始每次都翻倍,5次的重試時(shí)間間隔為1s, 2s, 4s, 8s, 16s,總共31s,第5次發(fā)出后還要等32s都知道第5次也超時(shí)了。如果第五次重傳之后,還未收到客戶端的 ACK,server 端的 TCP 才會(huì)把斷開這個(gè)連接。

          關(guān)于SYN Flood攻擊

          攻擊者短時(shí)間偽造不同 IP 地址的 SYN 報(bào)文,服務(wù)端每接收到一個(gè) SYN 報(bào)文,就進(jìn)入SYN_RCVD 狀態(tài),但服務(wù)端發(fā)送出去的 ACK + SYN 報(bào)文,無法得到未知 IP 主機(jī)的 ACK 應(yīng)答,久而久之就會(huì)占滿服務(wù)端的 SYN 接收隊(duì)列(未連接隊(duì)列),使得服務(wù)器不能為正常用戶服務(wù)。

          避免方式

          設(shè)置 tcp_syncookies = 1。當(dāng) SYN 隊(duì)列滿了后,TCP 會(huì)通過源地址端口、目標(biāo)地址端口和時(shí)間戳打造出一個(gè)特別的 Sequence Number 發(fā)回去(又叫cookie)。
          如果是攻擊者則不會(huì)有響應(yīng),如果是正常連接,則會(huì)把這個(gè) SYN Cookie 發(fā)回來,然后服務(wù)端可以通過 cookie 建連接。
          設(shè)置 netdev_max_backlog 的值,確定鏈接隊(duì)列的大小。當(dāng)網(wǎng)卡接收數(shù)據(jù)包的速度大于內(nèi)核處理的速度時(shí),會(huì)有一個(gè)隊(duì)列保存這些數(shù)據(jù)包。
          通過設(shè)置 netdev_max_backlog 的值,確定 SYN_RCVD 狀態(tài)連接的最大個(gè)數(shù)。
          通過設(shè)置 tcp_abort_on_overflow 的值。當(dāng)超出處理能時(shí),對(duì)新的 SYN 直接回報(bào) RST,丟棄連接。

          TCP四次揮手

          TCP的連接斷開

          TCP 一個(gè)特別的概念叫作半關(guān)閉,這個(gè)概念是說, TCP 的連接是全雙工(可以同時(shí)發(fā)送和接收)連接,因此在關(guān)閉連接的時(shí)候,必須關(guān)閉傳和送兩個(gè)方向上的連接。
          客戶機(jī)給服務(wù)器 FIN 的 TCP 報(bào)文,然后服務(wù)器返回給客戶端一個(gè)確認(rèn) ACK 報(bào)文,并且發(fā)送一個(gè)FIN 報(bào)文,當(dāng)客戶機(jī)回復(fù) ACK 報(bào)文后( 四次握手),連接就結(jié)束了。
          在建立連接的時(shí)候,通信的雙方要互相確認(rèn)對(duì)方的最大報(bào)文長度( MSS ),以便通信。
          一般這個(gè) SYN 長度是 MTU 減去固定 IP 首部和 TCP 首部長度。對(duì)于一個(gè)以太網(wǎng),一般可以達(dá) 1460 Byte 。當(dāng)然如果對(duì)于非本地的 IP ,這個(gè) MSS 可能就只有 536 Byte ,而且,如果中間的傳輸網(wǎng)絡(luò)的 MSS 更加的小的話,這個(gè)值還會(huì)變得更小。

          為什么建連接要三次握手,斷連接需要四次揮手?

          對(duì)于建連接的三次握手,主要是要初始化 Sequence Number 的初始值。通信的雙方要互相通知對(duì)方自己的初始化的 Sequence Numbe,所以叫 SYN 。
          這個(gè)號(hào)要作為以后的數(shù)據(jù)通信的序號(hào),以保證應(yīng)用層接收到的數(shù)據(jù)不會(huì)因?yàn)榫W(wǎng)絡(luò)上的傳輸問題而亂序( TCP 會(huì)用這個(gè)序號(hào)來拼接數(shù)據(jù))。
          對(duì)于四次揮手,其實(shí)仔細(xì)看則是兩次,因?yàn)?TCP 是全雙工的,所以,發(fā)送方和接收方都需要 FIN 和 ACK。
          只不過,有一方是被動(dòng)的,所以看上去就成了所謂的四次揮手 。如果兩邊同時(shí)斷連接,那就會(huì)就進(jìn)入到 CLOSING 狀態(tài),接著就是TIME_WAIT 狀態(tài)。

          斷開連接中的異常

          TIME_WAIT數(shù)量太多

          從上面的描述可以知道,TIME_WAIT 是個(gè)很重要的狀態(tài),但是如果在大并發(fā)的短鏈接下,TIME_WAIT 就會(huì)太多。TIME_WAIT過多會(huì)占用大量的內(nèi)存資源和端口資源。
          優(yōu)化法一:tcp_tw_reuse
          設(shè)置tcp_tw_reuse = 1,則可以復(fù)用處于 TIME_WAIT 的 socket 為新的連接所用。
          有一點(diǎn)需要注意的是,tcp_tw_reuse 功能只能用客戶端(連接發(fā)起方),因?yàn)殚_啟了該功能,在調(diào)用 connect() 函數(shù)時(shí),內(nèi)核會(huì)隨機(jī)找一個(gè) time_wait 狀態(tài)超過 1 秒的連接給新的連接復(fù)用。
          使用 tcp_timestamps = 1 選項(xiàng),還有一個(gè)前提,需要打開對(duì) TCP 時(shí)間戳的支持,即這個(gè)時(shí)間戳的字段是在 TCP 頭部的「選項(xiàng)」里,用于記錄 TCP 發(fā)送方的當(dāng)前時(shí)間戳和從對(duì)端接收到的最新時(shí)間戳。
          由于引入了時(shí)間戳,我們在前面提到的 2MSL 問題就不復(fù)存在了,因?yàn)橹貜?fù)的數(shù)據(jù)包會(huì)因?yàn)闀r(shí)間戳過期被自然丟棄。
          優(yōu)化法二:tcp_max_tw_buckets
          這個(gè)值默認(rèn)為 18000,當(dāng)系統(tǒng)中處于 TIME_WAIT 的連接一旦超過這個(gè)值時(shí),系統(tǒng)就會(huì)將后面的 TIME_WAIT 連接狀態(tài)重置。
          這個(gè)方法過于暴力,而且治標(biāo)不治本,帶來的問題遠(yuǎn)比解決的問題多,不推薦使用。

          TCP狀態(tài)流轉(zhuǎn)

          接下來再看一下著名的 TCP 狀態(tài)流轉(zhuǎn)圖。
          CLOSED狀態(tài):表示初始狀態(tài)。
          LISTEN狀態(tài):表示服務(wù)器端的某個(gè) socket 處于監(jiān)聽狀態(tài),可以接受連接。
          SYN_SENT狀態(tài):在服務(wù)端監(jiān)聽后,客戶端 socket 執(zhí)行 CONNECT 連接時(shí),客戶端發(fā)送 SYN 報(bào)文,此時(shí)客戶端就進(jìn)入 SYN_SENT 狀態(tài),等待服務(wù)端的確認(rèn)。
          SYN_RCVD狀態(tài):表示服務(wù)端接收到了SYN 報(bào)文,在正常情況下,這個(gè)狀態(tài)是服務(wù)器端的 socket 在建立 TCP 連接時(shí)的三次握手會(huì)話過程中的一個(gè)中間狀態(tài),很短暫,基本上用網(wǎng)絡(luò)查詢工具 netstat 是很難看到這種狀態(tài)的。因此這種狀態(tài)時(shí),當(dāng)收到客戶端的 ACK 報(bào)文后,它會(huì)進(jìn)入到 ESTABLISHED 狀態(tài)。
          ESTABLISHED狀態(tài):表示連接已經(jīng)建立了。
          FIN_WAIT_1狀態(tài):這個(gè)是已經(jīng)建立連接之后,其中一方請求終止連接,等待對(duì)方的 FIN 報(bào)文 。
          FIN_WAIT_1 狀態(tài)是當(dāng) socket 在 ESTABLISHED 狀態(tài)時(shí),它想主動(dòng)關(guān)閉連接,向?qū)Ψ桨l(fā)送了 FIN 報(bào)文,此時(shí)該 socket 即進(jìn)入到 FIN_WAIT_1 狀態(tài)。而當(dāng)對(duì)方回應(yīng) ACK 報(bào)文后,則進(jìn)入到 FIN_WAIT_2 狀態(tài)。
          當(dāng)然在實(shí)際的正常情況下,無論對(duì)方處于何種情況,都應(yīng)該馬上回應(yīng) ACK 報(bào)文,所以 FIN_WAIT_1 狀態(tài)一般是比較難見到的,而 FIN_WAIT_2 狀態(tài)還可以用 netstat 看到。
          FIN_WAIT_2狀態(tài):實(shí)際上 FIN_WAIT_2 狀態(tài)下的 socket ,表示半連接,即有一方要求關(guān)閉連接,但另外還告訴對(duì)方:我暫時(shí)還有點(diǎn)數(shù)據(jù)需要傳送給你,請稍后再關(guān)閉連接。
          TIME_ WAIT狀態(tài):表示收到了對(duì)方的 FIN 報(bào)文,并發(fā)送出了 ACK 報(bào)文,就等 2MSL 后即可回到 CLOSED 可用狀態(tài)了。如果在 FIN_WAIT_1 狀態(tài)下,收到了對(duì)方同時(shí)帶 FIN 標(biāo)志和 ACK 標(biāo)志的報(bào)文時(shí),可以直接進(jìn)入到 TIME_WAIT 狀態(tài),而無需經(jīng)過 FIN_WAIT_2 狀態(tài)。
          CLOSING狀態(tài):這種狀態(tài)比較特殊,實(shí)際情況中應(yīng)該是很少見。正常情況下,當(dāng)發(fā)送 FIN 報(bào)文后,按理來說是應(yīng)該先收到(或同時(shí)收到)對(duì)方的ACK 報(bào)文,再收到對(duì)方的 FIN 報(bào)文 。但是 CLOSING 狀態(tài)表示你發(fā)送 FIN 報(bào)文后,并沒有收到對(duì)方的 ACK 報(bào)文,反而收到了對(duì)方的 FIN 報(bào)文 。
          如果雙方幾乎在同時(shí)關(guān)閉一個(gè) socket 的話,那么就出現(xiàn)了雙方同時(shí)發(fā)送 FIN 報(bào)文的情況,就會(huì)出現(xiàn) CLOSING 狀態(tài),表示雙方都正在關(guān)閉 socket 連接。
          CLOSE_WAIT狀態(tài):表示在等待關(guān)閉。當(dāng)對(duì)方關(guān)閉一個(gè) socket 后發(fā)送 FIN 報(bào)文給自己時(shí),系統(tǒng)將毫無疑問地會(huì)回應(yīng) ACK 報(bào)文給對(duì)方,此時(shí)則進(jìn)入到 CLOSE_WAIT 狀態(tài)。
          接下來呢,實(shí)際上你真正需要考慮的事情是察看你是否還有數(shù)據(jù)發(fā)送給對(duì)方,如果沒有,那么你也就可以關(guān)閉這個(gè)socket了,發(fā)送 FIN 報(bào)文給對(duì)方,即關(guān)閉連接 。CLOSE _WAIT 狀態(tài)下,需要完成的事情是等待你去關(guān)閉連接。
          LAST_ACK狀態(tài):這個(gè)狀態(tài)還是比較好理解的,它是被動(dòng)關(guān)閉 方在發(fā)送 FIN 報(bào)文后,最后等待對(duì)方的 ACK 報(bào)文。
          CLOSED狀態(tài):當(dāng)收到 ACK 報(bào)文后,也即可以進(jìn)入到 CLOSED 可用狀態(tài)了。
          2MSL 等待狀態(tài):在 FIN_WAIT_2 發(fā)送了最后一個(gè) ACK 數(shù)據(jù)報(bào)以后,要進(jìn)入 TIME_WAIT 態(tài),這個(gè)狀態(tài)是防止最后一次握手的數(shù)據(jù)報(bào)沒有傳送到對(duì)方那里而準(zhǔn)備的。
          由于 socket 2MSL 狀態(tài),使得應(yīng)用程序在 2MSL 時(shí)間內(nèi)無法再次使用同一個(gè) socket ,對(duì)于客戶程序還好 些,但是對(duì)于服務(wù)程序(httpd),它總是要使用同一個(gè)端口來進(jìn)行服務(wù),而在 2MSL 時(shí)間內(nèi),啟動(dòng) httpd 就會(huì)出現(xiàn)錯(cuò)誤(插口被使用)。
          為了避免這個(gè)錯(cuò)誤,服務(wù)器給出了一個(gè)平靜時(shí)間的概念,這是說在 2MSL的時(shí)間內(nèi),雖然可以重新啟動(dòng)服務(wù)器,但是這個(gè)服務(wù)器還是要平靜地等待 2MSL 的時(shí)間才能進(jìn)行下一次連接。
          FIN WAIT_2 狀態(tài):這就是著名的半關(guān)閉狀態(tài)了,這是在關(guān)閉連接時(shí),客戶端和服務(wù)器兩次握手之后的狀態(tài) 。
          在這個(gè)狀態(tài)下,應(yīng)用程序還有接收數(shù)據(jù)的能力。已經(jīng)無法發(fā)送數(shù)據(jù),但是也有一種可能是,客戶端處于FIN_WAIT_2 狀態(tài),而服務(wù)器則一直處于 WAIT_CLOSE 狀態(tài),直到應(yīng)用層來決定關(guān)閉這個(gè)狀態(tài)。
          RST 同時(shí)打開和同時(shí)關(guān)閉:RST 是另一種關(guān)閉連接的方式,應(yīng)用程序應(yīng)該可以判斷RST 包的真實(shí)性,即是否為異常中止 而同時(shí)打開和同時(shí)關(guān)閉則是兩種特殊的 TCP 狀態(tài),發(fā)生的概率很小。

          總結(jié)

          本文主要講述了網(wǎng)絡(luò)分層模型,以及各層的作用,數(shù)據(jù)包是怎么組裝和拆包的。TCP 包結(jié)構(gòu)也大致學(xué)習(xí)了下,還有 TCP 連接的建立和斷開。
          TCP 連接建立之后才開始發(fā)數(shù)據(jù)包,所以 TCP 三次握手很重要。TCP 三次握手中也可能存在一些異常,只有徹底搞懂三次握手才能正確處理這些異常。
          TCP 四次揮手也很重要,server 中經(jīng)常要接受和斷開連接。對(duì)應(yīng)斷開連接中的異常,以及服務(wù)器請求量過多,只有在搞懂 TCP 四次揮手以后,處理這些問題才能得心應(yīng)手。
          - END -

          最近熱文

          ?  韋神!北大數(shù)學(xué)系韋東奕爆紅!拒絕哈佛offer,留任北大!
          ?  他是世界上最杰出程序員之一,1 個(gè)月寫了個(gè)操作系統(tǒng),退休后去做飛行員!
          ?  開掛的00后!17歲「天才少女」被8所世界名校錄取,最終選擇MIT計(jì)算機(jī)系
          ?  微信沙雕功能“炸屎”上線!網(wǎng)友:滿屏的粑粑真可愛

          瀏覽 39
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  性欧美性爱豆花视频 | 色老板成人无码版在线播放 | 国产一区二区三区乱伦 | 欧美三级专区 | 亲子乱婬A片日韩精品一区 |