网络基础2-3(TCP协议,三次握手,四次挥手,TIME_WAIT状态的作用,TCP如何保证可靠传输,TCP连接中状态转化,滑动窗口,流量控制,快速重传,拥塞窗口,延迟应答,捎带应答,粘包问题)
TCP協議
TCP協議概念
TCP全稱為 “傳輸控制協議(Transmission Control Protocol”). 人如其名, 要對數據的傳輸進行一個詳細的控制
TCP協議格式
1. 源/目的端口號: 表示數據是從哪個進程來, 到哪個進程去;
2. 32位序號/32位確認號: 后面詳細講;
3. 4位TCP報頭長度: 表示該TCP頭部有多少個32位bit(有多少個4字節(jié)); 所以TCP頭部大長度是15 * 4 = 60
4. 6位標志位:
5. 16位窗口大小
6. 16位校驗和
發(fā)送端填充, CRC校驗. 接收端校驗不通過, 則認為數據有問題. 此處的檢驗和不光包含TCP首部, 也 包含TCP數據部分.
7. 16位緊急指針
標識哪部分數據是緊急數據;
8. 40字節(jié)頭部選項
三次握手和四次揮手圖示
關于TCP協議的重點問題
1. 三次握手建立連接以及四次揮手斷開連接的流程?
三次握手過程
當客戶端調用connect時,觸發(fā)了連接請求,向服務器發(fā)送了SYN X包,這時connect進入阻塞狀態(tài);服務器監(jiān)聽到連接請求,即收到SYN X包,調用accept函 數接收請求向客戶端發(fā)送SYN K ,ACK X+1,這時accept進入阻塞狀態(tài);客戶端收到服務器的SYN K ,ACK X+1之后,這時connect返回,并對SYN K進行確認;服務器收到ACK K+1時,accept返回,至此三次握手完畢,連接建立。
總結:客戶端的connect在三次握手的第二個次返回,而服務器端的accept在三次握手的第三次返回。
四次揮手
2. 握手為什么是三次,揮手為什么是四次?
三次握手足以建立連接,四次握手就有些多余
如果兩次握手的話,就會出現已失效的請求報文段突然又傳送到了服務端而產生連接的誤判
例如:
有這樣一種情況,當A發(fā)送一個消息給B,但是由于網絡原因,消息被阻塞在了某個節(jié)點,然后阻塞的時間超出設定的時間,A會認為這個消息丟失了,然后重新發(fā)送消息。
當A和B通信完成后,這個被A認為失效的消息,到達了B
對于B而言,以為這是一個新的請求鏈接消息,就向A發(fā)送確認,
對于A而言,它認為沒有給B再次發(fā)送消息(因為上次的通話已經結束)所有A不會理睬B的這個確認,但是B則會一直等待A的消息
四次揮手
因為當Server端收到Client端的SYN連接請求報文后,可以直接發(fā)送SYN+ACK報文。其中ACK報文是用來應答的,SYN報文是用來同步的。但是關閉連接時,當Server端收到FIN報文時,很可能并不會立即關閉SOCKET,所以只能先回復一個ACK報文,告訴Client端,“你發(fā)的FIN報文我收到了”。只有等到我Server端所有的報文都發(fā)送完了,我才能發(fā)送FIN報文,因此不能一起發(fā)送。故需要四步握手。
3. 三次握手失敗,服務端是如何處理的?
失敗時服務器并不會重傳ack報文,而是直接發(fā)送RTS報文段,進入CLOSED狀態(tài)。這樣做的目的是為了防止SYN洪泛攻擊。
4. TIME_WAIT狀態(tài)的作用?
如果四次揮手中最后一個ACK丟了,那么服務端會再次發(fā)送一個FIN。如果沒有TIME_WAIT的話,那么客戶端直接關閉,有可能重新與別的服務器建立連接,此時用的還是原來的端口和IP,那么之前的服務端重新發(fā)送的FIN又發(fā)給了客戶端,此時客戶端就懵逼了,我才剛建立連接,怎么就要分手?
總結
MSL-----報文最大生存周期
等待1個MSL時間是為了能夠處理對端重傳的FIN包進行ACK回復
等待2個MSL時間是為了讓所有網絡中延遲的報文都消失在網絡中,不會對后續(xù)連接造成影響
5. 服務端出現大量TIME_WAIT狀態(tài)的原因以及解決方法
由于主動關閉TCP連接的一方才會進入TIME_WAIT狀態(tài),一般情況服務器端不會出現TIME_WAIT狀態(tài),因為大多數情況都是客戶端主動發(fā)起連接并主動關閉連接。但是某些服務如pop/smtp、ftp卻是服務端收到客戶端的QUIT命令后主動關閉連接,這就造成這類服務器上容易出現大量的TIME_WAIT狀態(tài)的連接,而且并發(fā)量越大處于此種狀態(tài)的連接越多。另外,對于被動關閉連接的服務在主動關閉客戶端非法請求或清理長時間不活動的連接時(這種情況很可能是客戶端程序忘記關閉連接)也會出現TIME_WAIT的狀態(tài)。
方法一
C/C++中提供了一個接口,如果服務器重啟時需要對端口號以及socket地址進行復用,從而避免了TIME_WAIT狀態(tài)
方法二
通過修改Linux內核的方式解決該問題
在 /etc/sysctl.conf中加入
net.ipv4.tcp_tw_recycle = 1 (表示開啟TCP連接中TIME-WAIT sockets的快速回收,默認為0,表示關閉)
net.ipv4.tcp_fin_timeout=30 (修改系統(tǒng)默認的 TIMEOUT 時間)
TCP的可靠傳輸
1. 確認應答機制
2. 超時重傳機制
超時的時間如何確定?
理想的情況下, 找到一個小的時間, 保證 “確認應答一定能在這個時間內返回”. 但是這個時間的長短, 隨著網絡環(huán)境的不同, 是有差異的. 如果超時時間設的太長, 會影響整體的重傳效率; 如果超時時間設的太短, 有可能會頻繁發(fā)送重復的包;
TCP為了保證無論在任何環(huán)境下都能比較高性能的通信, 因此會動態(tài)計算這個大超時時間.
3. 包序管理
TCP協議需要能夠識別出那些包是重復的包, 并且把重復的丟棄掉. 這時候我們利用序列號, 就可以很容易做到去重的效果.
序號+長度
TCP連接管理機制
服務端狀態(tài)轉化
客戶端狀態(tài)轉化
滑動窗口
一次性可以發(fā)送大量的數據(受限于協議字段中的窗口大小);然后等待回復
對每一個發(fā)送的數據段, 都要給一個ACK確認應答. 收到ACK后再發(fā)送下一個數據段. 這樣做有一個比較大的缺點, 就是性能較差. 尤其是數據往返的時間較長的時候.既然這樣一發(fā)一收的方式性能較低, 那么我們一次發(fā)送多條數據, 就可以大大的提高性能(其實是將多個段的等待時 間重疊在一起了).
服務端:接受數據,后沿往后走并回復客戶端,前沿不能動,客戶端拿走數據后,前沿往后走
客戶端:發(fā)送第一條數據,窗口不動,等到接受到第一條數據的回復后,后沿向后走,根據回復的窗口大小,決定前沿是否向后動
滑動窗口中快速重傳機制
如果出現了丟包, 如何進行重傳?
情況一: 數據包已經抵達, ACK被丟了.
這種情況下, 部分ACK丟了并不要緊, 因為可以通過后續(xù)的ACK進行確認;
只要后面有一次ack成功了,就代表前面的都接收到了
情況二: 數據包就直接丟了.
滑動窗口中數據的連續(xù)發(fā)送,盡力避免了因為ack丟失而導致的重傳
確認回復中的ACK確認序號能夠表示,這個序號之前的數據都已經接收到了
若前邊的數據沒有接受到,反而接收到了后邊的數據,則不會對后邊的數據進行ACK確認
總結:
當接收端接受數據的時候,若第一條數據沒到,但是接受到了第二條數據,認為第一條數據可能丟失,立即向發(fā)送端連續(xù)三次發(fā)送重傳請求;發(fā)送端連續(xù)接受到三條重傳請求,則對這條數據進行重傳
流量控制
接收端處理數據的速度是有限的. 如果發(fā)送端發(fā)的太快, 導致接收端的緩沖區(qū)被打滿, 這個時候如果發(fā)送端繼續(xù)發(fā)送, 就會造成丟包, 繼而引起丟包重傳等等一系列連鎖反應. 因此TCP支持根據接收端的處理能力, 來決定發(fā)送端的發(fā)送速度. 這個機制就叫做流量控制(Flow Control);
接收端如何把窗口大小告訴發(fā)送端呢?
TCP首部中, 有一個16位窗口字段, 就是存放了窗口大小信息;
16位數字大表示65535, 那么TCP窗口大就是65535字節(jié)么?
實際上, TCP首部40字節(jié)選項中還包含了一個窗口擴大因子M, 實際窗口大小是 窗口字段的值左移 M 位;
總結
TCP的擁塞窗口
TCP引入 慢啟動,快增長 機制, 先發(fā)少量的數據, 探探路, 摸清當前的網絡擁堵狀態(tài), 再決定按照多大的速度傳輸數據;
通信初始雙方協商窗口大小,窗口有可能很大,一次會發(fā)送很多數據,可能會因為網絡原因導致大量丟包,導致重傳,降低效率 發(fā)送端維護一個擁塞窗口,控制/限制發(fā)送端發(fā)送的數據最大大小,這個數字隨著每次ack的確認回復快速增長,但是一旦出現包重傳,則立即重新初始化少量的丟包, 我們僅僅是觸發(fā)超時重傳; 大量的丟包, 我們就認為網絡擁塞; 當TCP通信開始后, 網絡吞吐量會逐漸上升; 隨著網絡發(fā)生擁堵, 吞吐量會立刻下降; 擁塞控制, 歸根結底是TCP協議想盡可能快的把數據傳輸給對方, 但是又要避免給網絡造成太大壓力的折中方案.
TCP擁塞控制這樣的過程, 就好像 熱戀的感覺
TCP的延遲應答機制
盡可能保證窗口大小(因為接受方,有可能很快就會把數據從緩沖區(qū)拿走)
如果接收數據的主機立刻返回ACK應答, 這時候返回的窗口可能比較小
一定要記得, 窗口越大, 網絡吞吐量就越大, 傳輸效率就越高. 我們的目標是在保證網絡不擁塞的情況下盡量提高傳輸 效率;
那么所有的包都可以延遲應答么? 肯定也不是;
TCP捎帶應答機制
盡可能避免純報頭的確認回復
例如:
在延遲應答的基礎上, 我們發(fā)現, 很多情況下, 客戶端服務器在應用層也是 “一發(fā)一收” 的. 意味著客戶端給服務器說 了 “How are you”, 服務器也會給客戶端回一個 “Fine, thank you”; 那么這個時候ACK就可以搭順風車, 和服務器回應的 “Fine, thank you” 一起回給客戶端
面向字節(jié)流
對數據按照以字節(jié)為單位的流式傳輸
創(chuàng)建一個TCP的socket, 同時在內核中創(chuàng)建一個 發(fā)送緩沖區(qū) 和一個 接收緩沖區(qū);
由于緩沖區(qū)的存在, TCP程序的讀和寫不需要一一匹配, 例如:
寫100個字節(jié)數據時, 可以調用一次write寫100個字節(jié), 也可以調用100次write, 每次寫一個字節(jié); 讀100個字節(jié)數據時, 也完全不需要考慮寫的時候是怎么寫的, 既可以一次read 100個字節(jié), 也可以一次 read一個字節(jié), 重復100次;
粘包問題
tcp產生粘包就是內核并沒有對send要發(fā)送的數據進行明確的邊界區(qū)分。
那么如何避免粘包問題呢? 歸根結底就是一句話, 明確兩個包之間的邊界
思考: 對于UDP協議來說, 是否也存在 “粘包問題” 呢?
TCP斷開的體現
基于TCP應用層協議
總結
以上是生活随笔為你收集整理的网络基础2-3(TCP协议,三次握手,四次挥手,TIME_WAIT状态的作用,TCP如何保证可靠传输,TCP连接中状态转化,滑动窗口,流量控制,快速重传,拥塞窗口,延迟应答,捎带应答,粘包问题)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 战神4PC版多少钱
- 下一篇: [AI]人工智能早就可以拥有有大量的初级