偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

聊點TCP干貨

網絡 通信技術
我們在平時的開發(fā)中,或多或少都會涉獵到網絡傳輸這塊。這篇文章,主要是整理一下 TCP 的一些知識要點。

我們在平時的開發(fā)中,或多或少都會涉獵到網絡傳輸這塊。

這篇文章,主要是整理一下 TCP 的一些知識要點,作為一名開發(fā)者來說,盡管有那么多的基礎設施(框架、組件)幫我們屏蔽了這些細節(jié)。但我仍然認為了解它的一些基本原理必有些裨益,尤其是當你在分布式環(huán)境上遇到一些棘手問題時,一些原理性的知識可能會讓你快速找到答案。

[[266526]]

一、起源

TCP 是傳輸層的協(xié)議,全稱是叫做 Transmission Control Protocol,這個協(xié)議在 IETF RFC 793 進行了定義。

在互聯(lián)網產生之前,我們的電腦都是相互獨立的,每臺機器都有著自己的操作系統(tǒng)并保持著自己的運行。

于是,為了將這些電腦連接起來,并能夠基于一種"通道"的形式進行數(shù)據、資源的傳輸及交互,IETF 制定了 TCP 協(xié)議。

那么,IETF又是什么? 這是一個令人尊敬的技術組織,叫 Internet Engineering Task Force,即互聯(lián)網工程任務組。

這是一個成立于1985年的開放性組織,現(xiàn)在我們所提到的 HTTP、TCP、IP 這些重要的網絡協(xié)議,都是出自于該組織。

可以這么說,IETF 是互聯(lián)網的始作俑者,沒有它就沒有現(xiàn)在繁榮的互聯(lián)網了。

值得一提的是,IETF并非權貴組織,它是一個"來自民間" 的自組織、自管理的團隊,非常崇尚于自由平等的精神。

整個互聯(lián)網的底層機制是由一套標準網絡協(xié)議組成的,為了更方便于理解,人們便定義了所謂的“網絡分層模型"。

在學習計算機網絡課程的時候,都會提到兩種網絡模型,如下:

聊點 TCP 干貨

  • OSI 模型,全稱為 Open System Interconnection即開放系統(tǒng)互聯(lián)模型,這個是由 ISO(International Organization for Standardization) 國際標準化組織提出的。 它主要是用來解決當時各個網絡技術供應商在協(xié)議上無法統(tǒng)一的問題,通過將整個網絡體系結構抽象為 7層,從最底層的物理層、數(shù)據鏈路層一直到最上面的應用層都做了定義。

在以前,由于術語眾多,有許多人經常被OSI、ISO所迷惑..

  • TCP/IP,即 TCP/IP Protocol Suite(協(xié)議套件)是一個以TCP協(xié)議和IP協(xié)議為核心的通信模型,該模型采用協(xié)議堆棧的方式來實現(xiàn)許多通信協(xié)議,并將通訊體系抽象為4層。 TCP/IP 模型最早發(fā)源于美國國防部(縮寫為DoD)的ARPA網項目,此后就交由IETF組織來維護。

從上面的圖中可以看出,TCP/IP 基本上是OSI 模型的簡化版,當然也更加容易理解。

在網絡層以下,物理層、數(shù)據鏈路層所涉及的一些技術手段及概念都相對晦澀難懂,就比如光纜、中繼器、交換機等需要一些專業(yè)背景才能掌握通透。

對于大多數(shù)的軟件應用來說,將網絡層以下的部分統(tǒng)稱為“網絡接口層" 無疑是更加簡單的。

因此,OSI 模型盡管非常完善且全面,但已經被 TCP/IP 模型所淘汰,在互聯(lián)網應用盛行的今天很少被提及。

TCP/IP 網絡模型

圖-TCP/IP 網絡模型

二、TCP 協(xié)議

TCP 是整個 TCP/IP 協(xié)議族中最重要的傳輸層協(xié)議,它定義了一種面向連接的、可靠的、基于流的傳輸方式。

HTTP 是基于 TCP 的,所以說 TCP 是整個互聯(lián)網的協(xié)議其一并不為過。

同時,我們在使用 HTTP 協(xié)議實現(xiàn)應用系統(tǒng)間的交互時,也經常免不了會與 TCP 打上交道。因此有必要了解一些基本機制。

1. TCP 的特點?

  • 首先,TCP 是基于連接的,也就是在進行數(shù)據傳輸之前,客戶端與服務端(或者說是通信的雙方)需要先建立一個可信的連接。在數(shù)據傳輸結束后,再通過一種協(xié)定的方式斷開連接,由通信的雙方釋放資源。這里涉及到的,就是常說的"三次握手"、"四次揮手"
  • 其次,TCP 是可靠的,它定義了一種數(shù)據包的"超時重傳機制",簡單說,就是每一個數(shù)據包在發(fā)送出去后的都會等待一個響應。如果指定時間內沒有收到響應,由發(fā)送方進行一定次數(shù)的重傳來保證數(shù)據的可靠傳輸。
  • 最后,TCP 是基于流的,這是指在傳輸數(shù)據時應用層不需要關注數(shù)據包的邊界,TCP在數(shù)據傳輸時會自動根據網絡環(huán)境將數(shù)據進行緩沖、分組、合并。

這點跟基于報文的協(xié)議(UDP)是截然不同的。當然,基于流的傳輸也保證了數(shù)據收發(fā)的有序性,因此每個數(shù)據包都附帶上一個屬于當前連接的序列號。

2. 怎么理解全雙工?

全雙工是通訊上的術語,一般在軟件開發(fā)領域提到的并不多。

這是指數(shù)據同時在兩個方向上傳輸,TCP 是基于全雙工的可信傳輸協(xié)議。

當然 UDP 也可以實現(xiàn)全雙工的傳輸,但 TCP 只能實現(xiàn)點對點的傳輸,無法支持廣播或者多播(分組)

黑板:半雙工的區(qū)別在于,同一時間只能有一個方向的傳輸

3. TCP 的數(shù)據包如何組織?

透視一個協(xié)議的最原始的方法就是看它的數(shù)據包,一個TCP 的報文格式如下:

聊點 TCP 干貨

這里面的字段就包括了:

(1) 源端口:表明發(fā)送端所使用的端口號,用于目標主機回應。

(2) 目的端口:表明要連接的目標主機的端口號。

(3) 序號:表明發(fā)送的數(shù)據包的順序,一般為上次發(fā)送包中的順序號+1。

若該數(shù)據包是整個TCP連接中的第一個包(SYN包),則該值是隨機生成的。

(4) 確認號:表明本端TCP已經接收到的數(shù)據,其值表示期待對端發(fā)送的下一個字節(jié)的序號。

實際上告訴對方,在這個序號減1以前的字節(jié)已正確接收。

若該數(shù)據包是整個TCP連接中的第一個包(SYN包),則確認號一般為0。

(5) 數(shù)據偏移:表示以32位(4字節(jié))為單位的TCP分組頭的總長度(首部長度),用于確定用戶數(shù)據區(qū)的起始位置。

在沒有可變內容的情況下,TCP頭部的大小為20字節(jié),對應該值為5。

(6) 標志位:緊急標志位(URG):開啟時表明此數(shù)據包處于緊急狀態(tài)應該優(yōu)先處理

  • 確認標志位(ACK):開啟時表明確認號有效,否則忽略確認號
  • 推送標志位(PSH):開啟時表明應該盡快交付給應用進程,而不必等到緩存區(qū)填滿才推送,比如 telnet 的場景
  • 復位標志位(RST):開啟時表明TCP連接出現(xiàn)連接出現(xiàn)錯誤,數(shù)據包非法拒絕連接
  • 同步標志位(SYN):開啟時表明連接建立的標志
  • 終止標志位(FIN):開啟時表明釋放一個連接

(7) 窗口大小:表明期望接受到的數(shù)據包字節(jié)數(shù),用于擁塞控制。

(8) 校驗和:實現(xiàn)對TCP報文頭以及數(shù)據區(qū)進行校驗。

(9) 緊急指針:在緊急狀態(tài)下(URG打開),指出窗口中緊急數(shù)據的位置(末端)。

(10) 選項(可變):用于支持一些特殊的變量,比如最大分組長度(MSS)。

(11) 填充:用于保證可變選項為32 bit的整數(shù)倍。

黑板:一般情況下TCP 頭部為20字節(jié),加上20字節(jié)的 IP頭部,一個數(shù)據包至少包含40字節(jié)的頭部

三、TCP 工作流程

鏈是指鏈路,這個是物理層的概念,比如光纜光纖,或是無線的電磁波。

但這里所說的鏈路其實是網絡連接的意思,即 IP 上層的概念。

那么,一個TCP 正常的通訊流程,會包含建鏈(建立連接)、傳輸數(shù)據、拆鏈(關閉連接),

如下圖所示:

聊點 TCP 干貨

(圖來自網絡)

據上圖所示,在進行 TCP 進行數(shù)據傳輸時,都不可避免的會經過這兩個階段:

  • 三次握手建立連接
  • 執(zhí)行數(shù)據傳輸、雙方讀寫
  • 四次揮手釋放連接

下面,重點說明下建鏈與拆鏈的過程

四、 三次握手

聊點 TCP 干貨

在建立TCP連接時,需要經過三次交互,也成為三次握手(HandShake)。

  • 客戶端發(fā)起連接請求,發(fā)送 SYN包(SYN=i)到服務器,并進入到SYN-SEND狀態(tài),等待服務器確認
  • 服務器收到SYN包后,必須確認客戶的 SYN(ack=i+1),同時自己也發(fā)送一個SYN包(SYN=k),即SYN+ACK包,此時服務器進入SYN-RECV狀態(tài)
  • 客戶端收到服務器的SYN+ACK包,向服務器發(fā)送確認報ACK(ack=k+1),此后客戶端和服務器進入ESTABLISHED狀態(tài),雙方可以開始傳送數(shù)據。

在談論三次握手的時候,有幾個問題是需要關注的:

問題1. 為什么是三次握手

這個問題在技術面試時屢試不爽,原話是能不能兩次,或者是四次握手呢?

答案就是,TCP 是可靠的傳輸,在建立連接時就應該經過兩端的確認過程,如上面的流程,

只有在三次握手的情況下,客戶端和服務端都經過了一次真正(SYN+ACK)的確認過程。這樣的連接便認為是可信的。

此外,如果僅僅只是兩次握手,一旦網絡不穩(wěn)定造成 SYN 包重傳則會直接導致重復建立連接,浪費資源。

問題2. 什么是syn flood攻擊

syn flood 是一種經典的 ddos攻擊手段,這里面用到了TCP 三次握手存在的漏洞。

在上面的圖中,可以看到當服務端接收到 SYN 后進入 SYN-RECV 狀態(tài),此時的連接稱為半連接,同時會被服務端寫入一個 半連接隊列。

想象一下,如果攻擊者在短時間內不斷的向服務端發(fā)送大量的 SYN 包而不響應,那么服務器的 半連接隊列很快會被寫滿,從而導致無法工作。

實現(xiàn) syn flood 的手段,可以通過偽造源 IP 的方式,這樣服務器的響應就永遠到達不了客戶端(握手無法完成);

當然,通過設定客戶端防火墻規(guī)則也可以達到同樣的目的。

對 syn flood 實現(xiàn)攔截是比較困難的,可以通過啟用 syn_cookies 的方式實現(xiàn)緩解,但這通常不是最佳方案。

最好的辦法是通過專業(yè)的防火墻來解決,基本上所有的云計算大T 都具備這個能力。

問題3. 半連接隊列和全連接隊列如何調優(yōu)

這里提到了一個"半連接隊列"(syns queue),與其對應的還有一個 "全連接隊列"(accept queue)

前者用于暫存未建立完全的連接,后者是連接在成功建立后進入的一個隊列。

半連接隊列默認大小可以通過內核參數(shù)調整:

  1. echo 4096 >  /proc/sys/net/ipv4/tcp_max_syn_backlog 

黑板:tcpmaxsynbacklog 在 syncookies 開啟時是無效的,這兩個選項存在沖突

對于全連接隊列,如果服務器未能及時通過 accept 調用將其中的連接取走,會導致隊列溢出(連接失效)

全連接隊列的大小的內核調優(yōu)方式:

  1. echo  4096 >  /proc/ sys/net/core/somaxconn 

那么,是不是只有內核調優(yōu)這種方法能影響這兩個參數(shù)呢?答案是否定的。

實際上,在應用層調用 socket listen 時也支持設置一個 backlog參數(shù),這幾個之間的關系如下:

  1. 半連接隊列長度 = min(backlog,內核 net.core.somaxconn,內核 tcp_max_syn_backlog) 
  2. 全連接隊列長度 = min(backlog,內核 net.core.somaxconn) 

黑板:一般的應用服務器如 netty、tomcat 都支持設置 backlog 參數(shù),但是在真正進行調優(yōu)時還需要配合考慮內核參數(shù)的配置。

五、 四次揮手

聊點 TCP 干貨

在釋放連接時,由于TCP是全雙工的,因此最后要由兩端分別進行關閉,這個流程如下:

  • 客戶端發(fā)送一個FIN,用來關閉客戶端到服務器的數(shù)據傳送,客戶端進入FINWAIT1狀態(tài)。
  • 服務器收到FIN后,發(fā)送一個ACK給客戶端,確認序號為收到序號+1(與SYN相同,一個FIN占用一個序號),服務器進入CLOSEWAIT狀態(tài),而客戶端進入FINWAIT2狀態(tài)。
  • 服務器發(fā)送一個FIN,用來關閉服務器到客戶端的數(shù)據傳送,服務器進入LASTACK狀態(tài)。
  • 客戶端收到FIN后,客戶端進入TIMEWAIT狀態(tài),接著發(fā)送一個ACK給服務器,確認序號為收到序號+1,服務器進入CLOSED狀態(tài),完成釋放。

關閉連接有主動關閉和被動關閉一說,這里為了簡化理解,我們以客戶端作為主動關閉方,服務器為被動關閉方。

四次揮手需要關注的問題:

問題1. 為什么是四次揮手

發(fā)送FIN的一方就是主動關閉(客戶端),而另一方則為被動關閉(服務器)。

當一方發(fā)送了FIN,則表示在這一方不再會有數(shù)據的發(fā)送。

其中當被動關閉方受到對方的FIN時,此時往往可能還有數(shù)據需要發(fā)送過去,因此無法立即發(fā)送FIN(也就是無法將FIN與ACK合并發(fā)送),

而是在等待自己的數(shù)據發(fā)送完畢后再單獨發(fā)送FIN,因此整個過程需要四次交互。

問題2. 什么是半關閉

客戶端在收到第一個FIN的ACK響應后,會進入FINWAIT2 狀態(tài)時,此時服務器處于 CLOSEWAIT狀態(tài),這種狀態(tài)就稱之為半關閉。

從半關閉到全關閉,需要等待第二次FIN的確認才算結束。此時,客戶端要等到服務器的FIN才能進入TIMEWAIT,

如果對方遲遲不發(fā)送FIN呢,則會等待一段時間后超時,這個可以通過內核參數(shù)tcpfin_timeout控制,默認是60s。

問題3. 為什么服務器會有大量 closewait

半關閉的狀態(tài)下的服務器連接會處于 closewait 狀態(tài),直到服務器發(fā)送了FIN。

那么在應用層則是調用socket.close()會執(zhí)行FIN的發(fā)送,如果服務器出現(xiàn)大量CLOSE_WAIT狀態(tài)的連接,那么有可能的原因:

  • 服務器壓力過大,根本來不及調用close
  • 存在連接泄露問題(Bug),服務器未及時關閉連接

問題4. timewait 會帶來什么問題

當客戶端收到了對方的FIN時,會進入TIMEWAIT狀態(tài),此時會保持一段時間再進入CLOSE狀態(tài)。

這么做的原因主要還是為了可靠的關閉連接。在將TCP 進行可靠性設計之時就考慮了許多網絡的不穩(wěn)定性的因素,比如:

發(fā)送給對方的ACK 可能會無法及時收到,此時對方可能重傳FIN過來,如果提前進入CLOSE則會返回RST而不是ACK,就會影響關閉流程。

因此 TIMEWAIT 狀態(tài)默認會持續(xù)一段時間,直到確認不會再有重傳的數(shù)據包之后再安全的關閉。

黑板:這里timewait的持續(xù)時間默認是 2*MSL(總共1分鐘),這個MSL叫Max Segment Lifetime,也就是關于一個數(shù)據包在網絡中傳輸?shù)淖畲笊芷诘念A設。 MSL默認是30s,當然這個值在現(xiàn)在已經可以大幅度縮減??梢娫诋敃r在設計之初,網絡狀況有多么的糟糕。

那么timewait會帶來什么問題?

如果頻繁的主動關閉連接,可能會產生大量 timewait,由于timewait 的連接占用了一個句柄及少量內存(4K),那么就有可能會影響其他連接的建立,比如:

出現(xiàn) too many open files 異常..

該如何解決:

  • 重用連接,避免頻繁關閉,比如使用連接池
  • 參數(shù)調優(yōu),比如開啟tcptwreuse選項支持timewait連接的重復使用。

黑板:HTTP 協(xié)議里頭發(fā)現(xiàn)了timewait的問題,于是在 HTTP 1.1 中定義了 KeepAlive 用來支持連接的重用。

問題5. RST 是什么,為什么會出現(xiàn)

RST 是一個特殊的標記,用來表示當前應該立即終止連接。以下這些情況都會產生RST:

  • 向一個未被監(jiān)聽的端口發(fā)送數(shù)據
  • 對方已經調用 close 關閉連接
  • 存在一些數(shù)據未處理(接收緩沖區(qū)),請求關閉連接時,會發(fā)送RST強制關閉
  • 某些請求發(fā)生了超時

RST 機制有時候也會被利用,做一些端口的掃描,如下:

聊點 TCP 干貨

-> 端口開啟,可接受SYN

聊點 TCP 干貨

-> 端口關閉,響應RST

小結

原文只是想總結下 TCP 參數(shù)調優(yōu)的幾個細節(jié),沒想到TCP 牽扯出來的東西實在太多,光是一個簡單的握手、揮手流程就存在這么多的細節(jié)和坑。

可以說為了保證數(shù)據傳輸?shù)目煽啃裕缙诘脑O計者確實考慮了太多的東西。當然,這也為上層的應用實現(xiàn)鋪平了道路。

責任編輯:趙寧寧 來源: 美碼師
相關推薦

2020-12-17 08:00:18

java8時間類時間戳

2024-11-04 09:00:00

Java開發(fā)

2014-08-18 09:26:18

TCP

2020-05-22 08:16:07

PONGPONXG-PON

2021-01-28 22:31:33

分組密碼算法

2023-09-22 17:36:37

2011-07-06 11:13:29

iOS游戲開發(fā)

2018-06-07 13:17:12

契約測試單元測試API測試

2019-02-13 14:15:59

Linux版本Fedora

2020-10-15 06:56:51

MySQL排序

2018-11-29 09:13:47

CPU中斷控制器

2022-11-01 08:46:20

責任鏈模式對象

2021-02-06 08:34:49

函數(shù)memoize文檔

2021-01-29 08:32:21

數(shù)據結構數(shù)組

2022-08-08 08:25:21

Javajar 文件

2021-08-04 09:32:05

Typescript 技巧Partial

2023-07-06 13:56:14

微軟Skype

2023-05-15 08:38:58

模板方法模式

2019-12-17 10:06:18

CDMA高通4G

2022-03-08 16:10:38

Redis事務機制
點贊
收藏

51CTO技術棧公眾號