tcp/ip 需要知道的一些事
本文主要是最近看了以下《tcp/ip詳解 卷1》的部分小結,個人最感興趣的是 經典問題 40ms 延時 的問題!
個人建議著重看19-24章節。每章都有乾貨。
單播、多播、廣播、組播、泛播概念區分
ICMP
ICMP的作用
- 差錯控制
- “Ping”的過程實際上是ICMP協議工作的過程。還有其他的網路命令如跟蹤路由的Traceroute命令也是
tcp
幾個概念
msl 最長報文段存活時間
mss 最大報文段長度 ,主要是為了防止報文端被分段傳送。 如果超過1mss 將會被分段傳送。
定時器
- 重傳定時器
- 堅持(presist)定時器 視窗探查
- 保活(keepalive)定時器 就是心跳檢測
- 2MSL定時器 測量一個連線處於TIME_WAIT狀態的時間。
-
狀態流轉
常見的情況,比如server關了,埠依然佔用,其實就是處於TIME_WAIT狀態 ,2MSL超時,用於超時重傳最後的ack。
- 接收視窗和傳送視窗的區別
接收視窗是接收方發給傳送方的,(就是抓包看到的win= ),
傳送視窗是由sender根據receiver的接收視窗以及當前已傳送未ack的資料來自己計算的。tcp抓包看不到 - tcp 滑動視窗和擁塞視窗的區別
滑動視窗:滑動視窗不是真實存在的視窗,需要sender和recever共同作用。通告視窗(window offered by receiver) ,也就是我們抓包看到的win=xxx,是接收方使用的流量控制。
我們來分析一下1的情況,當sender 連續傳送資料給receiver的時候,如果receiver的應用層來不及把資料從核心recv buffer拷貝到應用buffer,那麼recv buffer會爆滿,這時候receiver ack win=0。然後sender會把資料一直拷貝到send buffer而send buffer不發給receiver,直到receiver ack win> 0。
由此可見,通告視窗win就是recv buffer的剩餘空間。
具體例子的分析可見 《tcp/ip 詳解1》p213 。我們可以簡單根據這個抓包的時序對滑動視窗進行分析。尤其我們看到 報文段8 win=3072.說明在receiver的recv buffer中還有1024個位元組未被應用層buffer拷貝過去。因此在圖2中可以看到的滑動視窗的通告視窗就是3072。
其實我們仔細想想看這裡貌似存在一個缺陷,如果receiver win=0 之後 通告的win>0 的ack報文段(比如圖1的報文段8)丟失了,那sender豈不是要一直等下去?
這個問題設計者早就發現了,採用了一個tcp堅持定時器。 sender週期性的向receiver 查詢,以便發現視窗是否已經增大。 這些sender發出去的報文段叫做視窗探查。
**tcp window scale ** :
由於緩衝區大小在TCP頭部只有16位來表示,所以它的最大值是65536,但是對於一些情況來說需要使用更大的滑動視窗,這時候就要使用擴充套件的滑動視窗,如光纖高速通訊網路,或者是衛星長連線網路,需要視窗儘可能的大。這時會使用擴充套件的32位的滑動視窗大小。
shift count 在tcp三次握手的時候確認
最終的calculated window size =2^7 × 227 =128 * 227 都可在上面找到對應的數值。
擁塞視窗:是傳送端維護的一個視窗,是傳送方使用的流量控制。主要就是維護cwnd。下面可以看到分析。
慢啟動和擁塞避免
超時重傳採用“指數退避演算法”
慢啟動和擁塞避免是兩個獨立的演算法,但通常一起作用。
需要維持的變數:
- 擁塞視窗 cwnd(預設初始化為1)
- 慢啟動門限 ssthresh(預設初始化為65535位元組)
擁塞演算法:
當擁塞發生時(超時或收到重複確認) ssthresh被設定為當前視窗大小的一半( cwnd和接收方通告視窗大小的最小值,但最少為 2個報文段) 。此外,如果是超時引起了擁塞,則c w n d被設定為1個報文段(這就是慢啟動) 。
前半段是慢啟動(由cwnd=1開始可判斷),後半段是擁塞避免。此時ssthresh是16個報文段大小。
擁塞避免的公式:
圖中都是收到重複ack的 擁塞避免。從圖中我們可以清晰的看到每個序號下降的地方就是一次重傳,共有3處,而且每處都只有一個下落點,因此可以得出每處只重傳了一個報文段。
對於cwnd的曲線,在每處發現重傳後,就
詳細分析參看《tcp/ip詳解》21章
延遲確認和Nagle演算法
延遲確認:接收端收到資料之後,並不立即傳送ACK確認收到資料,而是延遲傳送ACK,等待一段時間,以期望和沿該方向傳送的資料一起傳送。是為了提高網路效能,因為少發了幾次,然而,在某些情況下,該技術可以降低應用程式的效能。
Nagle演算法:儘可能傳送大塊資料,避免使網路中充斥小分組,從而減少傳送包的個數來增加網路的利用率。Nagle演算法要求在任意時刻,最多有一個未被確認的分組,在收到確認之前,小分組將被快取在傳送端。直到快取了一定量,等待了一定的時間,或者收到前一個資料的確認,才能傳送出去。由TCP_NODELAY選項控制。
我覺得: 這兩個主要是為了解決傳輸中 連續資料包都很小的情況,為了優化效能,而採用延遲確認和nagle,這樣在發的時候可以屯多一點資料一起發,應答的時候,把資料和ack一起帶過去。但是對於傳輸成塊資料的情況就不太適用了,這兩個預設都是開啟的,要注意適時關閉!!,否則會帶來資料傳輸延遲。所以一般我們實際工作中遇到由200ms以內的延時,可以懷疑下和tcp的延時ack,nagle演算法有無關係。
經典問題 40ms 延時
產生條件
- 延遲確認與Nagle演算法相互作用
- 延遲確認與擁塞控制相互作用
延遲確認與Nagle演算法相互作用
- 延時ack
如果收到的資料內容大於一個MSS, 傳送ACK;(大部分情況是這個)
如果收到了接收視窗以外的資料, 傳送ACK;
如果處於quick mode, 傳送ACK;
如果收到亂序的資料, 傳送ACK;
其他, 延遲傳送ACK
延遲ack其實是動態變化的,跟 Pingpong 這個值有關。
Pingpong是一個狀態值, 用來標識當前tcp互動的狀態, 以預測是否是W-R-W-R-W-R這種互動式的通訊模式(互動資料流), 如果處於(=1), 可以用延遲ack。
我們來看以下這個圖。
當檢測到是互動資料流時 ,Pingpong=1,啟用了延時ack。當出現一個延遲純ack時取消互動模式 Pingpong=0;
- Nagle演算法
如果傳送內容大於等於1個MSS, 立即傳送;
如果之前沒有包未被確認, 立即傳送;
如果之前有包未被確認, 快取傳送內容;
如果收到ack, 立即傳送快取的內容。
如果該包含有FIN,則允許傳送;
設定了TCP_NODELAY選項,則允許傳送;
接下來分析以一下下面的情況:
1 00:44:37.878027 IP 172.25.38.135.44792 > 172.25.81.16.9877: S 3512052379:3512052379(0) win 5840 <mss 1448,wscale 7>
2 00:44:37.878045 IP 172.25.81.16.9877 > 172.25.38.135.44792: S 3581620571:3581620571(0) ack 3512052380 win 5792 <mss 1460,wscale 2>
3 00:44:37.879080 IP 172.25.38.135.44792 > 172.25.81.16.9877: . ack 1 win 46
......
4 00:44:38.885325 IP 172.25.38.135.44792 > 172.25.81.16.9877: P 1321:1453(132) ack 1321 win 86
5 00:44:38.886037 IP 172.25.81.16.9877 > 172.25.38.135.44792: P 1321:1453(132) ack 1453 win 2310
6 00:44:38.887174 IP 172.25.38.135.44792 > 172.25.81.16.9877: P 1453:2641(1188) ack 1453 win 102
7 00:44:38.887888 IP 172.25.81.16.9877 > 172.25.38.135.44792: P 1453:2476(1023) ack 2641 win 2904
8 00:44:38.925270 IP 172.25.38.135.44792 > 172.25.81.16.9877: . ack 2476 win 118
9 00:44:38.925276 IP 172.25.81.16.9877 > 172.25.38.135.44792: P 2476:2641(165) ack 2641 win 2904
10 00:44:38.926328 IP 172.25.38.135.44792 > 172.25.81.16.9877: . ack 2641 win 134
前三個報文段是三次握手,可以看出172.25.81.16.9877 為server,172.25.38.135.44792為client
4,5,6,7 是client和server互相互動資料流,並且8 出現了40ms延時ack,這個流程符合我們上面的流程分析。我們可看到延時ack是在client端開啟了,server端開啟了nagle演算法。
在報文段5到達client時,client就知道了這是互動資料流,所以開啟延時ack。當7發給client時,由於cleint並不需要傳送什麼資料給server,所以ack就一直等著定時器超時溢位,我們看到這時候延遲了40ms。
由於8報文段,即位元組序號2476的ack一直沒來,並且server端開啟著nadle演算法(如果之前有包未被確認, 快取傳送內容),所以報文段9 在收到8後才發。
40ms 這個是時間不同系統可能預設不同,rethat 預設40ms
解決延時的方案
對於這個例子而言
client
- client端關閉延遲ack
但是, 每個tcp請求都返回一個ack包, 導致網路包量的增加,需要斟酌 - 設定TCP_QUICKACK屬性。 但是需要每次recv後再設定一次。
server
- 關閉nagel演算法,即設定TCP_NODELAY。
staticvoid_set_tcp_nodelay(intfd) {
intenable =1;
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY,(void*)&enable,sizeof(enable));
}
但這樣會導致網路中出現很多小於1mss的報文段,因此最好能將這些小報文段先快取起來,大於1mss的時候再發出去,這樣這個mss 會被分段,1個正好是1mss,1個小於1mss,cilent連續收到這兩個分段後,判斷接受到的資料大於1mss,因此,立即傳送ack。無延遲。
延遲確認與擁塞視窗相互作用
前提傳送方(關閉Nagle),接收方(啟用延時ack)
同樣分析,即比如接收方mss大小1460 ,傳送方連續發了三個資料大小為100的報文段,此時到達了擁塞視窗cwnd=3,不能在傳送了,那麼接收方接受到300<1460 ,所以接收方也會出現40ms延時ack。
縮短延時方案
參考 http://www.jianshu.com/p/6f795599e4ab * 為什麼是40ms?這個時間能不能調整呢?* 這段。
【參考文章】
總結TCP的一些演算法或者實現方式,在我們平常開發中的應用和可借鑑的地方
- 滑動視窗
- 超時重傳
- 延遲確認和Nagle演算法 :優化延時
[附送 好文推薦]
關注我的公眾號,看更多好文!
相關文章
- sqlzoo需要知道的那些事SQL
- TCP/IP 知道這些就夠用了TCP
- 關於 TCP 需要了解的事兒TCP
- Flutter 你需要知道的那些事 01Flutter
- 關於CSS Transition,你需要知道的事CSS
- 獨立遊戲開發者需要知道的事實遊戲開發
- React 初學者需要知道的一些知識React
- 關於 Git 你需要知道的一些事情Git
- 關於webpack優化,你需要知道的事(上篇)Web優化
- 遊戲首次測投前,你需要知道的那些事......遊戲
- 成功部署AIOps需要知道的7件事AI
- socket,TCP/IP的理解TCP
- TCP TCP/IP HTTP HTTPSTCPHTTP
- 程式設計師最應該知道的一些事程式設計師
- 關於 Git 你所不知道的一些事Git
- Github Atom 你所不知道的一些事Github
- TCP/IP之TCP的建立與終止TCP
- TCP/IP族TCP
- TCP/IP模型TCP模型
- TCP / IP AT命令TCP
- TCP/IP基礎知識&Oracle的TCP/IP網路應用TCPOracle
- 關於進入遊戲行業你需要知道的事遊戲行業
- SQL Server DBA需要知道的三件事XTSQLServer
- IIS各個版本中你需要知道的那些事兒
- Web前端開發規範文件你需要知道的事Web前端
- TCP/IP、UDP/IP協議TCPUDP協議
- 【TCP/IP】TCP詳解筆記TCP筆記
- TCP/IP、Http的區別TCPHTTP
- Windows Container 和 Docker:你需要知道的5件事WindowsAIDocker
- 參加web前端學習前需要知道的注意事項Web前端
- Android Studio vs Eclipse:你需要知道的那些事AndroidEclipse
- tcp/ip協議TCP協議
- TCP/IP 筆記TCP筆記
- 面試之TCP/IP面試TCP
- TCP/IP 基礎TCP
- 淺談TCP/IPTCP
- TCP/IP 和SocketTCP
- TCP/IP故障排除TCP