Tcp協議基礎和常見面試問題

本篇文章是在看了別人的一些文章後,用於自己記錄使用

在之前先列出一些有關的基礎知識

OSI七層模型與TCP/IP四層模型

在這裏插入圖片描述

在這裏插入圖片描述

TCP/IP模型的層間通信與數據封裝

  • 數據包在網絡設備之間進行傳輸的過程中,爲了保證數據包準確地發送到目的地,發送端會對數據包進行封裝(在每一層都加上頭部信息)。
  • 在發送的數據包上附加TCP或者是UDP的包頭形成數據段segment,網絡層會添加IP包頭形成數據包Packet,數據鏈路層會給數據添加以太網包頭和FCS包尾,形成數據幀Frame,最後轉換成二進制的比特流通過物理線路傳到接收方。這個操作過程就叫做數據封裝,而對數據包進行處理時通信雙方所遵循和協商好的規則稱爲協議。
  • 接收端收到數據後會進行解封裝,從物理層開始,進行與發送端相反的操作,一層層去掉包頭,最終使應用層程序獲取到數據信息,使得發送方和接收方數據通信完成。

TCP

TCP 是一個協議,接下來要了解下

  • TCP特點
  • TCP和UCP的區別
  • TCP 協議頭部中每個字段的信息含義
  • TCP 的三次握手和四次揮手
TCP特點
  • TCP是面向連接的傳輸層協議
  • TCP鏈接是點對點的(套接字)
  • TCP提供可靠交付的服務
  • TCP提供全雙工通道
  • 面向字節流

TCP和UCP的區別

『』 TCP UDP
是否鏈接 面向連接 面向非鏈接
連接方式 點到點(套接字) 一對一,一對多,多對一,多對多
傳輸可靠性 可靠 不可靠(它只管發送,不管對方是否收到的)
是否有擁塞控制 面向字節流,有擁塞控制 面向報文,無擁塞控制(實時性好,如IP電話,實時視頻會議)
邏輯通信信道 全雙工的可靠信道 不可靠信道
應用場合 傳輸大量數據 少量數據
速度
大小 無限制 每個數據包64K
  • TCP面向連接(如打電話要先撥號建立連接);UDP是無連接的,即發送數據之前不需要建立連接
  • TCP提供可靠的服務。也就是說,通過TCP連接傳送的數據,無差錯,不丟失,不重複,且按序到達;UDP盡最大努力交付,即不保證可靠交付
  • TCP面向字節流,有流量擁塞控制。實際上是TCP把數據看成一連串無結構的字節流;UDP是面向報文的,UDP沒有擁塞控制,因此網絡出現擁塞不會使源主機的發送速率降低(對實時應用很有用,如IP電話,實時視頻會議等)
  • 每一條TCP連接只能是點到點的;UDP支持一對一,一對多,多對一和多對多的交互通信
  • TCP的邏輯通信信道是全雙工的可靠信道,UDP則是不可靠信道
一. TCP 協議頭部中每個字段的信息含義

在這裏插入圖片描述

在這裏插入圖片描述

Header Length
  • Head 的大小 , 用 4 bit 表示 , 4 bit 的最大值爲 15 , 單位是 32-bit , 所以 20 byte ≤ Header Length ≤ 60 byte 。
Source Port 和 Destination Port
  • Source Port 和 Destination Port 分別佔用16位
  • 表示源端口號和目的端口號,用於區分主機中的不同進程
  • IP地址用來區分不同主機的,源端口號和目的端口號配合上IP首部中的源IP地址就能確定爲一個TCP連接
32位序號(SequenceNumber)
  • 是包的序號,用來解決網絡包亂序(reordering)問題
  • 用來標識從TCP 發送端向TCP 接收端的數據字節流
  • 一次TCP通信(從TCP連接建立到斷開)過程中某一個傳輸方向上的字節流的每個字節的編號。
  • 假設主機A和主機B進行TCP通信,A發送給B的第一個TCP報文段中,序號值被系統初始化爲某個隨機值ISN(Initial Sequence Number,初始序號值)。那麼在該傳輸方向上(從A到B),後續的TCP報文段中序號值將被系統設置成ISN加上該報文段所攜帶數據的第一個字節在整個字節流中的偏移。例如,某個TCP報文段傳送的數據是字節流中的第1025~2048字節,那麼該報文段的序號值就是ISN+1025.另外一個傳輸方向(從B到A)的TCP報文段的序號值也具有相同的含義
32位確認號(Acknowledge number)
  • 就是ACK——用於確認收到,用來解決不丟包的問題
  • 用作對另一方發送來的TCP報文段的響應。
  • 其值是收到的TCP報文段的序號值加1。
  • 只有ACK=1時,確認序號字段纔有效,Ack=Seq+1
  • 假設主機A和主機B進行TCP通信,那麼A發送出的TCP報文段不僅攜帶自己的序號,而且包含對B發送來的TCP報文段的確認號。反之,B發送出的TCP報文段也同時攜帶自己的序號和對A發送來的報文段的確認號。
DataOffset(數據偏移(即首部長度))
  • 佔4個字節,它指出TCP報文段的數據起始處距離TCP報文段的起始處有多遠
  • 給出頭部佔32比特的數目
  • 沒有任何選項字段的TCP頭部長度爲20字節(5x32=160比特);最多可以有60字節的TCP頭部。
Reserved(保留字段)
  • 佔6位,保留爲今後使用,但目前應置爲0
TCPFlag(標誌位)
  • 佔6位,分別表示6個標誌;它們可多個同時被設置爲1,主要是用於操控TCP的狀態機,分爲緊急URG,確認ACK,推送PSH(Push),復位RST(ReSeT),同步SYN,終止FIN(FINis),下面會有詳細說明
windows size(窗口大小)
  • 佔16比特。
  • 是TCP流量控制的一個手段。這裏說的窗口,指的是接收通告窗口(Receiver Window,RWND)。它告訴對方本端的TCP接收緩衝區還能容納多少字節的數據,這樣對方就可以控制發送數據的速度。
Checksum(檢驗和)
  • 佔2字節。
  • 檢驗的範圍包括:TCP頭部和TCP數據這兩部分。
  • 在計算檢驗和時,要在TCP報文段的前面加上12字節的僞首部
UrgentPointers(緊急指針字段):
  • 佔16位,指出在本報文段中緊急數據共有多少個字節(緊急數據放在本報文段數據的最前面)。
  • 它是一個偏移量,和序號字段中的值相加表示緊急數據最後一個字節的序號
Option(選項字段)
  • TCP頭部的最後一個選項字段(options)是可變長的可選信息。
  • 0:選項表結束(1 byte)
  • 1:無操作(1 byte)用於選項字段之間的字邊界對齊。
  • 2:最大報文段長度(4 byte,Maximum Segment Size,MSS)通常在創建連接而設置SYN標誌的數據包中指明這個選項,指明本端所能接收的最大長度的報文段。通常將MSS設置爲(MTU-40)byte,攜帶TCP報文段的IP數據報的長度就不會超過MTU,從而避免本機發生IP分片。只能出現在同步報文段中,否則將被忽略。
  • 3:窗口擴大因子(4 byte,wscale),取值0-14。用來把TCP的窗口的值左移的位數,使窗口值乘倍。只能出現在同步報文段中,否則將被忽略。這是因爲現在的TCP接收數據緩衝區(接收窗口)的長度通常大於65535 byte。
  • 4:sackOK—發送端支持並同意使用SACK選項。
  • 5:SACK實際工作的選項。
  • 8:時間戳(10 byte,TCP Timestamps Option,TSopt)
    發送端的時間戳(Timestamp Value field,TSval,4 byte)
    時間戳回顯應答(Timestamp Echo Reply field,TSecr,4 byte)
  • 這部分最多包含40字節,因爲TCP頭部最長是60字節(其中還包含前面討論的20字節的固定部分)
TCPFlag (每一位佔 1 bit)
  • URG(urgent緊急):當URG= 1 時,表示TCP 包的緊急指針域有效,用來保證TCP連接不被中斷,並督促中間層設備要儘快處理這些數據(它告訴系統此報文段中有緊急數據,應儘快傳送(相當於高優先級的數據))
  • ACK(acknowledgement確認):當ACK= 1 時,表示確認號字段有效,當ACK= 0 時,確認號無效
  • PSH(push傳送):這個標誌位標識push操作,push操作就是在數據包到達接收端以後,立即傳送給應用程序,而不是在緩衝區排隊
  • RST(reset重置):當RST= 1 時,表明TCP連接需要釋放連接,然後再重新建立連接,也被用來拒絕錯誤和非法的數據包
  • SYN(synchronous建立聯機):表示同步序號,用來建立連接。SYN標誌位和ACK標誌位搭配使用,當連接請求的時候,SYN=1,ACK=0;連接被響應的時候,AYN=1,ACK=1。這個標誌的數據包常常被用來進行端口掃描。掃描者發送一個只有SYN的數據包,如果對方主機響應了一個數據包回來,就表明這臺主機存在這個端口,但是由於這種掃描只是進行TCP三次握手的第一次握手,因此這種掃描的成功表明被掃描的機器很不安全,一臺安全的主機將會強制要求一個連接嚴格的進行TCP的三次握手
  • FIN(finish結束):表示發送端已經達到數據末尾,也就是說雙方數據傳送完成,沒有數據可以傳送了,發送FIN 標誌位的TCP數據包後,連接將斷開,要求釋放運輸連接

二、TCP 3次握手和4次揮手

TCP 3次握手
TCP 3次握手的目的作用
  • TCP是面向連接的,無論哪一方向另一方發送數據之前,都必須現在雙方之間建立一條連接。在TCP/IP協議中,TCP協議提供可靠的連接服務
  • 所謂三次握手(Three-way Handshake),是指建立一個TCP連接時,需要客戶端和服務器總共發送3個包。
  • 三次握手的目的是連接服務器指定端口,建立TCP連接,並同步連接雙方的序列號和確認號並交換 TCP 窗口大小信息
  • 在socket編程中,客戶端執行connect()時。將觸發三次握手。

在這裏插入圖片描述

  • 第一次握手:建立連接,客戶端發送連接請求報文(將標誌位SYN置爲1,隨機產生一個值seq=J)到服務器,並進入SYN_SENT(請求鏈接狀態),等待服務器確認
  • 第二次握手:服務器收到數據包後通過標誌位SYN=1 知道客戶端請求建立連接,服務端並將標誌位SYN和ACK都置爲1,ack=J+1,隨機產生一個值seq=K,並將數據包發送給客戶端以確認連接請求,服務端進入SYN_RCVD 狀態(正在等待處理的請求數據)
  • 三次握手:客戶端收到服務器的數據包後,檢查ack是否爲J+1,ACK是否爲1,如果正確則將標誌位ACK置爲1,ack=K+1,並將該數據包發送給服務端,服務端檢查ack是否爲K+1,ACK是否爲1,如果正確則連接建立成功,客戶端和服務器進入ESTABLISHEN(TCP鏈接成功)狀態,完成三次握手,隨後客戶端與服務端之間可以開始傳輸數據
需要注意的是:
  • (A)不要將確認序號ack與標誌位中的ACK搞混了。
  • (B)確認方ack=發起方Seq+1,兩端配對。
SYN攻擊:

在三次握手過程中,Server發送SYN-ACK之後,收到Client的ACK之前的TCP連接稱爲半連接(half-open connect),此時Server處於SYN_RCVD狀態,當收到ACK後,Server轉入ESTABLISHED狀態。SYN攻擊就是Client在短時間內僞造大量不存在的IP地址,並向Server不斷地發送SYN包,Server回覆確認包,並等待Client的確認,由於源地址是不存在的,因此,Server需要不斷重發直至超時,這些僞造的SYN包將產時間佔用未連接隊列,導致正常的SYN請求因爲隊列滿而被丟棄,從而引起網絡堵塞甚至系統癱瘓。SYN攻擊時一種典型的DDOS攻擊,檢測SYN攻擊的方式非常簡單,即當Server上有大量半連接狀態且源IP地址是隨機的,則可以斷定遭到SYN攻擊了

四次揮手

在這裏插入圖片描述

  • 四次揮手(Four-Way Wavehand)即終止TCP連接,就是指斷開一個TCP連接時,需要客戶端和服務端總共發送4個包以確認連接的斷開。
  • 在socket編程中,這一過程由客戶端或服務端任一方執行close來觸發
  • 由於TCP連接時全雙工的,因此每個方向都必須要單獨進行關閉
  • 這一原則是:當一方完成數據發送任務後,發送一個FIN來終止這一方向的連接
  • 收到一個FIN只是意味着這一方向上沒有數據流動了,即不會再收到數據了,但是在這個TCP連接上仍然能夠發送數據,直到這一方向也發送了FIN
  • 首先進行關閉的一方將執行主動關閉,而另一方則執行被動關閉
揮手過程
  • 第一次揮手: client —> server 發送一個FIN,用來關閉 client -> server 的數據傳送,client進入FIN_WAIT_1狀態
  • 第二次揮手. server 收到FIN後,還可以繼續發送數據,所以發送ACK給server,確認序號爲收到序號+1(與SYN相同,一個FIN佔用一個序號),server進入CLOSE_WAIT狀態
  • 第三次揮手. server發送一個FIN,server -> client 的數據傳送,server 進入LAST_ACK 狀態
  • 第四次揮手. client收到FIN後,client 進入TIME_WAIT 狀態,接着發送一個ACK給Server,確認序號爲收到序號+1,server進入CLOSED 狀態,完成四次揮手

常見問題

【問題1】爲什麼建立連接是三次握手,而關閉連接卻是四次揮手呢?
  • 因爲服務端在LISTEN狀態下,收到建立連接請求的SYN報文後,把ACK和SYN放在一個報文裏發送給客戶端。
  • 而關閉連接時,當收到對方的FIN報文時,僅僅表示對方不再發送數據了但是還能接收數據,己方也未必全部數據都發送給對方了,所以己方可以立即close,也可以發送一些數據給對方後,再發送FIN報文給對方來表示同意現在關閉連接,因此,己方ACK和FIN一般都會分開發送
【問題2】爲什麼TIME_WAIT狀態需要經過2MSL(最大報文段生存時間)才能返回到CLOSE狀態?
  • 雖然按道理,四個報文都發送完畢,我們可以直接進入CLOSE狀態了,但是我們必須假象網絡是不可靠的,有可以最後一個ACK丟失。
  • 所以TIME_WAIT狀態就是用來重發可能丟失的ACK報文。在Client發送出最後的ACK回覆,但該ACK可能丟失。
  • Server如果沒有收到ACK,將不斷重複發送FIN片段。所以Client不能立即關閉,它必須確認Server接收到了該ACK。
  • Client會在發送出ACK之後進入到TIME_WAIT狀態。
  • Client會設置一個計時器,等待2MSL的時間。如果在該時間內再次收到FIN,那麼Client會重發ACK並再次等待2MSL。所謂的2MSL是兩倍的MSL(Maximum Segment Lifetime)。
  • MSL指一個片段在網絡中最大的存活時間,2MSL就是一個發送和一個回覆所需的最大時間。
  • 如果直到2MSL,Client都沒有再次收到FIN,那麼Client推斷ACK已經被成功接收,則結束TCP連接。
【問題3】爲什麼不能用兩次握手進行連接?
  • 3次握手完成兩個重要的功能,既要雙方做好發送數據的準備工作(雙方都知道彼此已準備好),也要允許雙方就初始序列號進行協商,這個序列號在握手過程中被髮送和確認。
  • 3次握手主要是爲了防止已失效的請求連接報文忽然又傳送到了,從而產生錯誤。
  • 假定A向B發送一個連接請求,由於一些原因,導致A發出的連接請求在一個網絡節點逗留了比較多的時間。此時A會將此連接請求作爲無效處理 又重新向B發起了一次新的連接請求,B正常收到此連接請求後建立了連接,數據傳輸完成後釋放了連接。如果此時A發出的第一次請求又到達了B,B會以爲A又發起了一次連接請求,如果是兩次握手:此時連接就建立了,B會一直等待A發送數據,從而白白浪費B的資源。 如果是三次握手:由於A沒有發起連接請求,也就不會理會B的連接響應,B沒有收到A的確認連接,就會關閉掉本次連接
【問題4】三次握手的第三個ACK包丟失
  • 當Client端收到Server的SYN+ACK應答後,其狀態變爲ESTABLISHED,併發送ACK包給Server;
  • 如果此時ACK在網絡中丟失,那麼Server端該TCP連接的狀態爲SYN_RECV,並且依次等待3秒、6秒、12秒後重新發送SYN+ACK包,以便Client重新發送ACK包。
  • server重發SYN+ACK包的次數,可以通過設置/proc/sys/net/ipv4/tcp_synack_retries修改,默認值爲5。
  • 如果重發指定次數後,仍然未收到ACK應答,那麼一段時間後,Server自動關閉這個連接。
  • 但是Client認爲這個連接已經建立,如果Client端向Server寫數據,Server端將以RST包響應,方能感知到Server的錯誤
【問題5】如果已經建立了連接,但是客戶端突然出現故障了怎麼辦?
  • TCP還設有一個保活計時器,客戶端如果出現故障,服務器不能一直等下去,白白浪費資源。
  • 服務器每收到一次客戶端的請求後都會重新復位這個計時器,時間通常是設置爲2小時,若兩小時還沒有收到客戶端的任何數據,服務器就會發送一個探測報文段,以後每隔75秒鐘發送一次。若一連發送10個探測報文仍然沒反應,服務器就認爲客戶端出了故障,接着就關閉連接。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章