網(wǎng)絡(luò)編程(1)-TCP問題分析

主目錄見:Android高級進(jìn)階知識(這是總目錄索引)
[written by 無心追求]

TCP問題分析

網(wǎng)絡(luò)的五層協(xié)議

  • 物理層
  • 數(shù)據(jù)鏈路層
  • 網(wǎng)絡(luò)層丧蘸,IP協(xié)議锨苏,ICMP協(xié)議(ping)
  • 傳輸層,傳輸層有兩個協(xié)議浴麻,面向連接的TCP和無連接的UDP郭卫,TCP是點(diǎn)對點(diǎn)的可靠連接,保證數(shù)據(jù)順序必達(dá)页藻,UDP是無連接的桨嫁,不保證數(shù)據(jù)順序必達(dá),UDP的傳輸效率要比TCP高份帐,但是可能會丟包璃吧,而且一個UDP分段最多只能發(fā)送65535個字節(jié),TCP則是數(shù)據(jù)流的形式進(jìn)行數(shù)據(jù)傳輸?shù)姆暇常瑢τ趹?yīng)用層來說畜挨,并沒有限制一次性可發(fā)送的數(shù)據(jù),只有在TCP協(xié)議這一層會對應(yīng)用層傳輸下來的數(shù)據(jù)做分段重組噩凹,這個跟SYN的MMS(Max segment size)有關(guān)巴元,表示TCP往另一端發(fā)送的最大塊數(shù)據(jù)的長度
  • 應(yīng)用層,F(xiàn)TP驮宴,HTTP逮刨,HTTPS,STMP等這些基于TCP協(xié)議實(shí)現(xiàn)的堵泽,而DNS修己,DHCP(動態(tài)主機(jī)配置協(xié)議,一種局域網(wǎng)協(xié)議)等是基于UDP協(xié)議實(shí)現(xiàn)的
    image.png

TCP協(xié)議

  • TCP協(xié)議的Header組成迎罗,TCP協(xié)議首部箩退,如果除去Options(選項(xiàng))的長度,有20個字節(jié)長度佳谦,IP協(xié)議首部也有20個字節(jié)的長度


    ![tcp1.jpg](http://upload-images.jianshu.io/upload_images/1609288-0260d9484bc76dfb.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

TCP三次握手

[圖片上傳中...(tcp3.jpg-a081f-1513993970933-0)]

[圖片上傳中...(tcp4.jpg-9173c2-1513993970933-1)]

這邊有幾個比較重要的點(diǎn)戴涝,主機(jī)A發(fā)起SYN,假設(shè)序號Seq為a,發(fā)送成功后A進(jìn)入了SYN_SENT狀態(tài)啥刻,主機(jī)B收到A發(fā)的SYN后給一個SYN+ACK奸鸯,發(fā)送成功后B進(jìn)入SYN_RCVD狀態(tài),假設(shè)序號Seq為b可帽,那么確認(rèn)號Ack必須為a+1娄涩,以此來標(biāo)記確實(shí)收到了A發(fā)過來的SYN,同時也說明下一次A要是再發(fā)消息過來映跟,那么序號Seq必須是a+1蓄拣,主機(jī)A收到B發(fā)過來的SYN+ACK后,進(jìn)入ESTABLISHED狀態(tài)努隙,表示A的TCP已經(jīng)可用球恤,然后再回復(fù)一個ACK給B,序號Seq為a+1荸镊,確認(rèn)號Ack為b+1咽斧,B收到后狀態(tài)也變?yōu)镋STABLISHED狀態(tài),這時候TCP的三次握手就完成了

TCP四次揮手

tcp7.jpg
tcp6.jpg

和三次握手比較類似躬存,主機(jī)A主動發(fā)送FIN张惹,Seq為a,ack為x岭洲,然后A進(jìn)入FIN_WAIT1狀態(tài)宛逗,B進(jìn)入CLOSE_WAIT狀態(tài),主機(jī)B收到A發(fā)過來的FIN之后盾剩,先回復(fù)一個FIN+ACK雷激,Seq為b,ack為a+1彪腔,然后B進(jìn)入LAST_ACK狀態(tài)侥锦,主機(jī)A收到B發(fā)的FIN+ACK后进栽,回復(fù)一個ACK德挣,Seq為a+1,Ack為b+1快毛,A進(jìn)入TIME_WAIT狀態(tài)格嗅,B收到A的ACK后,進(jìn)入CLOSED唠帝,然后A會再等一小段時間(2MSL超時)后進(jìn)入CLOSED狀態(tài)屯掖,TCP4次揮手完成,其實(shí)從抓包來看襟衰,并沒有發(fā)生四次交互贴铜,因?yàn)锽的ACK和FIN合并在一起發(fā)出去了,這個也是TCP傳輸?shù)囊环N策略,減少一次交互绍坝,增加了網(wǎng)絡(luò)的效率徘意,4次揮手我認(rèn)為是邏輯上的4個步驟

以下內(nèi)容都特么是從書里抄的

  • TIME_WAIT狀態(tài)也稱為2MSL等待狀態(tài)。每個具體TCP實(shí)現(xiàn)必須選擇一個報(bào)文段最大生
    存時間MSLMaximum Segment Lifetime)轩褐。它是任何報(bào)文段被丟棄前在網(wǎng)絡(luò)內(nèi)的最長時間椎咧。
    我們知道這個時間是有限的,因?yàn)門CP報(bào)文段以IP數(shù)據(jù)報(bào)在網(wǎng)絡(luò)內(nèi)傳輸把介,而IP數(shù)據(jù)報(bào)則有限制
    其生存時間的TTL字段
  • 當(dāng)TCP執(zhí)行一個主動關(guān)閉勤讽,并發(fā)回最后一個ACK,該連接必須在TIME_WAIT狀態(tài)停留的時間為2倍的MSL拗踢。這樣可讓TCP再次發(fā)送最后的ACK以防這個ACK丟失(另一端超時并重發(fā)最后的FIN)
  • 在FIN_WAIT_2狀態(tài)我們已經(jīng)發(fā)出了FIN脚牍,并且另一端也已對它進(jìn)行確認(rèn)。除非我們在實(shí)
    行半關(guān)閉秒拔,否則將等待另一端的應(yīng)用層意識到它已收到一個文件結(jié)束符說明莫矗,并向我們發(fā)一
    個FIN來關(guān)閉另一方向的連接。只有當(dāng)另一端的進(jìn)程完成這個關(guān)閉砂缩,我們這端才會從FIN_WAIT_2狀態(tài)進(jìn)入TIME_WAIT狀態(tài)作谚,這意味著我們這端可能永遠(yuǎn)保持這個狀態(tài),另一端也將處于CLOSE_WAIT狀態(tài)庵芭,并一直保持這個狀態(tài)直到應(yīng)用層決定進(jìn)行關(guān)閉

TCP選項(xiàng)

  • MSS最大報(bào)文長度就是其中一個選項(xiàng)
  • Timestamps時間戳(TCP Option - Timestamps: TSval 4294941817, TSecr 0)TSval為發(fā)起端發(fā)送這個消息包的本地時間妹懒,TSecr為發(fā)起端收到對方消息包的發(fā)送時間,即對方消息包中的TSval双吆,由于這個是SYN包眨唬,所以此時并沒有收到任何對方的消息,TSecr為0
  • Window scale窗口擴(kuò)大因子好乐,用來控制Window窗口的大小

擁塞控制

Nagle算法
  • 該算法要求一個TCP連接上最多只能有一個未被確認(rèn)的未完成的小分組匾竿,在該分組的確認(rèn)到達(dá)之前不能發(fā)送其他的小分組。相反蔚万,TCP收集這些少量的分組岭妖,并在確認(rèn)到來時以一個分組的方式發(fā)出去。該算法的優(yōu)越之處在于它是自適應(yīng)的:確認(rèn)到達(dá)得越快反璃,數(shù)據(jù)也就發(fā)送得越快昵慌。而在希望減少微小分組數(shù)目的低速廣域網(wǎng)上排龄,則會發(fā)送更少的分組
/**
     * Enable/disable TCP_NODELAY (disable/enable Nagle's algorithm).
     *
     * @param on <code>true</code> to enable TCP_NODELAY,
     * <code>false</code> to disable.
     *
     * @exception SocketException if there is an error
     * in the underlying protocol, such as a TCP error.
     *
     * @since   JDK1.1
     *
     * @see #getTcpNoDelay()
     */
    public void setTcpNoDelay(boolean on) throws SocketException {
        if (isClosed())
            throw new SocketException("Socket is closed");
        getImpl().setOption(SocketOptions.TCP_NODELAY, Boolean.valueOf(on));
    }

以上是應(yīng)用層提供的是否開啟Nagle算法的接口肤视,默認(rèn)為false,即開啟Nagle算法


tcp9.jpg
tcp10.jpg

這個是未用Nagle算法的抓包信息

滑動窗口
tcp11.jpg

對于發(fā)送方來說:

  1. Sent and Acknowledged:這些數(shù)據(jù)表示已經(jīng)發(fā)送成功并已經(jīng)被確認(rèn)的數(shù)據(jù)弧哎,這些數(shù)據(jù)其實(shí)的位置是在窗口之外了梧田,因?yàn)榇翱趦?nèi)順序最低的被確認(rèn)之后淳蔼,要移除窗口侧蘸,實(shí)際上是窗口進(jìn)行合攏,同時打開接收新的帶發(fā)送的數(shù)據(jù)
  2. Send But Not Yet Acknowledged:這部分?jǐn)?shù)據(jù)稱為發(fā)送但沒有被確認(rèn)鹉梨,數(shù)據(jù)被發(fā)送出去闺魏,沒有收到接收端的ACK,認(rèn)為并沒有完成發(fā)送俯画,這個屬于窗口內(nèi)的數(shù)據(jù)
  3. Not Sent析桥,Recipient Ready to Receive:這部分是盡快發(fā)送的數(shù)據(jù),這部分?jǐn)?shù)據(jù)已經(jīng)被加載到緩存中艰垂,也就是窗口中了泡仗,等待發(fā)送,其實(shí)這個窗口是完全有接收方告知的猜憎,接收方告知還是能夠接受這些包娩怎,所以發(fā)送方需要盡快的發(fā)送這些包
  4. Not Sent,Recipient Not Ready to Receive: 這些數(shù)據(jù)屬于未發(fā)送胰柑,同時接收端也不允許發(fā)送的截亦,因?yàn)檫@些數(shù)據(jù)已經(jīng)超出了發(fā)送端所接收的范圍

對于接收方來說:

  1. Received and ACK Not Send to Process:這部分?jǐn)?shù)據(jù)屬于接收了數(shù)據(jù)但是還沒有被上層的應(yīng)用程序接收,也是被緩存在窗口內(nèi)
  2. Received Not ACK: 已經(jīng)接收柬讨,但是還沒有回復(fù)ACK崩瓤,這些包可能輸屬于Delay ACK的范疇了
  3. Not Received:有空位,還沒有被接收的數(shù)據(jù)

窗口的動態(tài)調(diào)整:

  1. 客戶端給服務(wù)器發(fā)送了50個字節(jié)踩官,然后服務(wù)器回了Ack却桶,并且告知Win=0,客戶端收到服務(wù)器的Ack之后發(fā)現(xiàn)服務(wù)器這時候已經(jīng)不能夠接收數(shù)據(jù)了蔗牡,客戶端就會把數(shù)據(jù)先緩存起來颖系,并不在發(fā)送數(shù)據(jù),等收到服務(wù)器的窗口更新后Win=20辩越,發(fā)現(xiàn)服務(wù)器重新能夠接收20個字節(jié)了嘁扼,這時候客戶端才繼續(xù)發(fā)送數(shù)據(jù),這里其實(shí)也就是流量控制黔攒,同時避免過多的數(shù)據(jù)寫入到網(wǎng)絡(luò)鏈路中趁啸,加入鏈路的帶寬很小,過多的數(shù)據(jù)寫入會造成擁塞
慢啟動
  • 慢啟動為發(fā)送方的TCP增加了另一個窗口:擁塞窗口(congestion window)亏钩,記為cwnd莲绰;當(dāng)與另一個網(wǎng)絡(luò)的主機(jī)建立 TCP連接時欺旧,擁塞窗口被初始化為 1個報(bào)文段(即另一端通告的報(bào)文段大泄贸蟆);每收到一個ACK辞友,擁塞窗口就增加一個報(bào)段(cwnd以字節(jié)為單位栅哀,但是慢啟動以報(bào)文段大小為單位進(jìn)行增加)震肮;發(fā)送方取擁塞窗口與通告窗口中的最小值作為發(fā)送上限;擁塞窗口是發(fā)送方使用的流量控制留拾,而通告窗口則是接收方使用的流量控制
擁塞避免
  • ssthresh戳晌,這個是一個閥值,當(dāng)cwnd小于這個閥值的時候采用慢啟動痴柔,那么cwnd就會以指數(shù)增長沦偎,當(dāng)cwnd大于ssthresh的時候,這時候就不用慢啟動算法咳蔚,改用擁塞避免算法豪嚎,擁塞避免算法是在每次收到消息的ack的時候cwnd增加1,這時候cwnd就變成線性增長
快速重傳
  • 連續(xù)收到3次或者3次以上的重復(fù)Ack谈火,就會觸發(fā)一次快速重傳

超時重傳

  • RTT侈询,消息包發(fā)送和收到Ack的往返時間,每一個消息包的RTT都可能不一樣糯耍,TCP會根據(jù)消息包的RTT去計(jì)算下一次重傳的時間間隔扔字,RTT的計(jì)算公式是:R← R+ ( 1- )M,這里的 是一個推薦值為 0.9的平滑因子温技,每次進(jìn)行新測量的時候革为,這個被平滑的RTT將得到更新,每個新估計(jì)的90%來自前一個估計(jì)舵鳞,而10%則取自新的測量
  • RTO(Retransmission TimeOut)篷角,這個是重傳超時時間,也就是下重傳消息需要等待Ack的時間系任,超過這個時間就再次發(fā)起下一次重傳

TCP抓包分析

  • wireshark工具來查看tcpdump的抓包
  • 對于有root過的android手機(jī)恳蹲,如果手機(jī)系統(tǒng)中已經(jīng)內(nèi)置了tcpdump,可以直接使用tcpdump命令開啟抓包:tcpdump -i any -p -w /sdcard/netlog/dumpFileName俩滥,這個是我平時比較常用的抓包命令嘉蕾,是全部都抓,無論是無線網(wǎng)卡還是數(shù)據(jù)網(wǎng)絡(luò)霜旧,這種抓包命令在網(wǎng)絡(luò)切換错忱,網(wǎng)絡(luò)斷線重連的時候依然能保持抓包,如果采用指定數(shù)據(jù)網(wǎng)絡(luò)的抓包挂据,例如:tcpdump -i “aaa” -p -w /sdcard/netlog/dumpFileName以清,其中“aaa”是數(shù)據(jù)網(wǎng)絡(luò)的一個名稱,那當(dāng)設(shè)備網(wǎng)絡(luò)從數(shù)據(jù)網(wǎng)絡(luò)切換到無限網(wǎng)絡(luò)崎逃,這時候抓包就會斷了掷倔,或者數(shù)據(jù)網(wǎng)絡(luò)斷線重連這時候抓包也會停止,因此推薦采用any的抓包方式个绍,輸入命令后可以用ps | grep tcpdump命令看下抓包進(jìn)程是否運(yùn)行
  • 如果手機(jī)系統(tǒng)中把tcpdump模塊給裁剪掉勒葱,那么需要去網(wǎng)上下載tcpdump浪汪,然后執(zhí)行如下步驟:
adb push tcpdump /sdcard/ 
adb Shell 
su 
cat /sdcard/tcpdump > /system/bin/tcpdump

上一條命令如果提示沒有權(quán)限,接著執(zhí)行如下命令嘗試給 /system 目錄增加寫權(quán)限:

su
mount

在mount結(jié)果中找到包含/system的一行凛虽,類似如下:

/dev/block/platform/msm_sdcc.1/by-name/system /system ext4 ro,seclabel,relatime,data=ordered 0 0  

去處/system前半行死遭,即/dev/block/platform/msm_sdcc.1/by-name/system,執(zhí)行如下命令:

mount -o remount /dev/block/platform/msm_sdcc.1/by-name/system /system

這個時候/system就擁有寫權(quán)限了凯旋,繼續(xù)執(zhí)行:

cat /sdcard/tcpdump > /system/bin/tcpdump 
chmod 777 /system/bin/tcpdump  

到此為止呀潭,tcpdump就成功安裝到了/system/bin/目錄下,接著用如下命令還是抓包

Java中的Socket異常分析

connection reset
  • 在TCP消息協(xié)議包中至非,RST標(biāo)志代表連接終止蜗侈,對于應(yīng)用層來說可能會報(bào)connection reset
  • 當(dāng)A發(fā)送一個消息包給B,但是遲遲沒有收到B的Ack睡蟋,這時候A開始重傳踏幻,并且重傳一直不成功,知道最后一次重傳失敗之后戳杀,A會發(fā)起一個reset標(biāo)志
  • 當(dāng)A關(guān)閉的TCP連接该面,這時候還收到B發(fā)過來的數(shù)據(jù),A會立馬觸發(fā)一個reset
SocketException: Software caused connection abort
  • 這個異常對于Android來說信卡,是設(shè)備斷網(wǎng)了隔缀,同時會有一個網(wǎng)絡(luò)切換廣播
socket closed
  • 當(dāng)java中的socket被close掉之后,如果繼續(xù)往socket中寫數(shù)據(jù)傍菇,就會報(bào)socket closed異常
SocketTimeoutException:connect timeout/ConnectException: Connection timed out
  • 從字面意義上來理解就是連接超時猾瘸,從抓包層面來看就是A對B發(fā)起一個TCP連接,那么A就會發(fā)起一個SYN丢习,但是遲遲沒有收到B的SYN+ACK牵触,這時候SYN會進(jìn)入重傳,應(yīng)用層通常會設(shè)置一個連接超時時間咐低,當(dāng)這個連接超時時間溢出的時候就會報(bào)超時異常


    tcp12.jpg
UnknowHostException
  • 通常采用域名去連接的時候揽思,域名會先通過dns解析成ip最終去用ip連接,但是在dns解析ip的時候沒有解析出ip或者解析失敗就會報(bào)這個異常见擦,dns是采用udp協(xié)議钉汗,在Android設(shè)備上會連續(xù)連續(xù)嘗試8次,每次超時時間為5秒鲤屡,因此如果dns解析超時损痰,一共耗時40秒,也就是說:
InetSocketAddress inetSocketAddress = new InetSocketAddress(hostInfo.getHostname(), hostInfo.getPort());

這個代碼會卡40秒酒来,具體抓包信息如下:


tcp13.jpg
ConnectException:network is unreachable
  • 這個很明顯卢未,網(wǎng)絡(luò)不可用會報(bào)此異常
NoRouteToHostException: No route to host
  • 這個是由于DHCP(Dynamic Host Configuration Protocol,動態(tài)主機(jī)配置協(xié)議役首,使用UDP協(xié)議)租約過期造成的尝丐,在局域網(wǎng)中,DHCP的主要作用就是給局域網(wǎng)中的設(shè)備分配IP衡奥,分配策略如下:
  1. 自動分配方式(Automatic Allocation)爹袁,DHCP服務(wù)器為主機(jī)指定一個永久性的IP地址,一旦DHCP客戶端第一次成功從DHCP服務(wù)器端租用到IP地址后矮固,就可以永久性的使用該地址
  2. 動態(tài)分配方式(Dynamic Allocation)失息,DHCP服務(wù)器給主機(jī)指定一個具有時間限制的IP地址,時間到期或主機(jī)明確表示放棄該地址時档址,該地址可以被其他主機(jī)使用
  3. 手工分配方式(Manual Allocation)盹兢,客戶端的IP地址是由網(wǎng)絡(luò)管理員指定的,DHCP服務(wù)器只是將指定的IP地址告訴客戶端主機(jī)
    三種地址分配方式中守伸,只有動態(tài)分配可以重復(fù)使用客戶端不再需要的地址绎秒,也就是說動態(tài)分配的IP地址是可能被回收的,如果一臺設(shè)備分配的IP被回收了尼摹,那這臺設(shè)備的網(wǎng)絡(luò)就不可用见芹,這時候如果往再和外網(wǎng)去建立socket連接,就會報(bào)NoRouteToHostException: No route to host異常蠢涝,那么為了給IP續(xù)約玄呛,Android設(shè)備中會去實(shí)現(xiàn)DHCP協(xié)議,定期30分鐘去發(fā)起一個DHCP請求來更新IP信息和二,保持設(shè)備網(wǎng)絡(luò)可用徘铝,但是當(dāng)這個DHCP請求失敗的時候,此時IP要是過了有效時段惯吕,那么這段時間內(nèi)的設(shè)備網(wǎng)絡(luò)是無法訪問外網(wǎng)的惕它,直到DHCP請求重試成功為止
Connection Refused
  • 連接被拒絕,通撤系牵客戶端向服務(wù)器的指定端口發(fā)起一個TCP連接怠缸,要是服務(wù)器的并沒有監(jiān)聽這個端口,此時會拒絕TCP連接钳宪,會報(bào)Connection Refused異常
TCP端口重用
  • 在同一個進(jìn)程中揭北,一個端口如果已經(jīng)被一條TCP占用,那么當(dāng)?shù)诙lTCP連接還想申請使用這個端口的時候會報(bào)端口重用異常
socket read返回-1
  • -1就是文件結(jié)束符(EOF)吏颖,如果A和B之間有一條TCP連接搔体,A端的socket的read的時候返回-1,那這條socket就不再有可讀取的數(shù)據(jù)半醉,造成這個-1的原因是B端的TCP發(fā)起了一個FIN疚俱,可能是調(diào)用了socket的close方法

tcpdump抓包分析

tcp dup ack
  • 重復(fù)的Ack,#前面的數(shù)組表示丟包的包序號缩多,后面表示第幾次丟失呆奕,之所以會重復(fù)的Ack是可能是因?yàn)樵诰W(wǎng)絡(luò)延遲較高养晋,或者鏈路擁塞的時候一個包重傳了多次,但是重傳的這幾次最終都被收到了梁钾,在接收端第一次收到這個包的時候?qū)@個包進(jìn)行了Ack绳泉,然后再收到后面幾次重傳,再回復(fù)重復(fù)的Ack
tcp out of order
  • 收到的包是亂序的姆泻,TCP協(xié)議確保消息必達(dá)并且順序零酪,但是TCP協(xié)議是基于IP協(xié)議的,IP報(bào)文并不確保消息的順序性拇勃,所以先發(fā)出的IP報(bào)文可能比后發(fā)的IP報(bào)文先到達(dá)四苇,這里可能是鏈路擁塞,網(wǎng)絡(luò)延遲方咆,丟包月腋,Client到Server有多條網(wǎng)絡(luò)路徑導(dǎo)致IP報(bào)文到達(dá)的順序發(fā)生亂序,TCP協(xié)議在收到消息包后發(fā)現(xiàn)如果順序亂了瓣赂,就緩存起來暫時步拋給應(yīng)用層罗售,直到前面的消息包都收到為止,然后再重新組織消息的順序钩述,拋給應(yīng)用層寨躁,所以在實(shí)際場景中tcp out of order并不一定是代表異常,但是看到tcp out of order發(fā)生之后可能就懷疑鏈路是否發(fā)生擁塞牙勘,或者網(wǎng)絡(luò)延遲职恳,丟包等等來去判斷此時網(wǎng)絡(luò)是否穩(wěn)定
tcp retransmission
  • TCP協(xié)議既然要保證消息必達(dá),所以在一個消息發(fā)送出去之后方面,就會等待對方確認(rèn)收到這個消息的Ack放钦,在消息發(fā)送出去之后會啟動一個定時器來檢測是否在規(guī)定時間內(nèi)有收到Ack,如果沒有收到Ack恭金,這時候就會觸發(fā)此消息重傳操禀,這里還涉及到RTT(消息的回顯時間),RTO(消息重傳超時)横腿,每一次消息包發(fā)送都可能(這里并不一定會觸發(fā)RTT計(jì)算颓屑,要看這時候的計(jì)算RTT的定時器是否啟動,如果啟動耿焊,那么這次消息包發(fā)送就不會計(jì)算RTT)會不斷的去調(diào)整計(jì)算RTT揪惦,然后根據(jù)計(jì)算出來的RTT,再根據(jù)指定的公式計(jì)算出RTO
  • 關(guān)于超時重傳的一個疑問:當(dāng)有一個消息包正在TCP底層進(jìn)行重傳的過程中罗侯,應(yīng)用層此時再寫入數(shù)據(jù)的話器腋,那寫入的這個數(shù)據(jù)會再發(fā)送出去嗎?我的解答是:1.如果發(fā)生了超時重傳,那此時可能就存在網(wǎng)絡(luò)擁塞纫塌,tcp協(xié)議針對網(wǎng)絡(luò)擁塞控制就有幾種策略诊县,Nagle算法,滑動窗口措左,慢啟動依痊,擁塞避免,快速重傳后快速恢復(fù)(擁塞避免)媳荒;在Nagle算法的情況下抗悍,由于改算法需要等待上次消息的Ack回來之后才把后面的消息寫入到網(wǎng)絡(luò)中驹饺,所以此時應(yīng)用層寫入的數(shù)據(jù)并不會發(fā)送出去钳枕;而對于滑動窗口,如果接收窗口(提供窗口)為0赏壹,那數(shù)據(jù)也不會發(fā)送出去鱼炒;對于慢啟動,慢啟動還是需要在前一條消息的Ack回來之后才允許后續(xù)消息繼續(xù)發(fā)送蝌借,擁塞窗口只是控制發(fā)送消息的大小昔瞧,防止向網(wǎng)絡(luò)中寫入過多的數(shù)據(jù)加重?fù)砣凰詰?yīng)用層如果在TCP底層有一個消息正在重傳菩佑,此時再寫入一個數(shù)據(jù)的話自晰,此數(shù)據(jù)如果立即發(fā)送并且超時那么有可能在目前已有重傳過程中一起被發(fā)送出去(此操作需要根據(jù)當(dāng)前的接收窗口是否允許發(fā)送這么大的數(shù)據(jù)或者根據(jù)擁塞窗口是否發(fā)送這個大的數(shù)據(jù)來決定新寫入的數(shù)據(jù)是否跟著重傳一起發(fā)送出去),也有可能一直緩存這稍坯,等待上一個重傳成功收到Ack之后才寫出去
12-17 10:03:40.994  2725  2960 I SYNC-PUSH: {ConnectionService$7.onWrite--1} write [107] bytes.

12-17 10:04:02.234  2725  3052 I SYNC-PUSH: {ConnectionService$7.onWrite--1} write [7] bytes.
tcp14.jpg

應(yīng)用層將107字節(jié)發(fā)寫入之后酬荞,發(fā)生了重傳,這時候在10:04:02秒又寫入7個字節(jié)瞧哟,我們在抓包的時候發(fā)現(xiàn)重傳并沒有把這7個字節(jié)一起發(fā)送出去混巧,說明這個7個字節(jié)被暫時緩存起來了,此時有可能是網(wǎng)絡(luò)擁塞了勤揩,所以就不再向鏈路中發(fā)送數(shù)據(jù)避免加重網(wǎng)絡(luò)擁塞咧党,如果此時并不是網(wǎng)絡(luò)擁塞,那么有可能這7個字節(jié)就在重傳過程中被一起發(fā)送出去

tcp fast retransmission
  • 快速重傳陨亡,快速重傳是當(dāng)預(yù)測到鏈路可能存在擁塞的時候傍衡,連續(xù)收到了三次重復(fù)的Ack,快速重傳之后進(jìn)入快速恢復(fù)算法(擁塞避免负蠕,cwnd擁塞窗口線性增加)


    tcp15.jpg
tcp previous segment not captured
  • 這個是指前一個消息包還沒有收到聪舒,后一個消息包先收到

上圖,發(fā)生tcp previous segment not captured的消息包Sequence number: 1242674817虐急,重傳的消息包Sequence number: 1242674796箱残,但是1242674817先到了,而1242674796后到,所以在收到1242674817的時候會提示有漏掉一個segment數(shù)據(jù)被辑,1242674817會緩存起來并不會馬上通知給應(yīng)用層燎悍,直到1242674796到了之后一起通知給應(yīng)用層

seq,ack盼理,tsval谈山,tsecr
  • seq是消息的序號,ack是消息的確認(rèn)號宏怔,確認(rèn)號是確認(rèn)上一條消息已經(jīng)被收到奏路,并且告知發(fā)送端下一次發(fā)過來的消息的序列號
  • tsval是發(fā)送端發(fā)送這條消息的時間戳,tsecr是接收到對方消息的時間戳
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末臊诊,一起剝皮案震驚了整個濱河市鸽粉,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌抓艳,老刑警劉巖触机,帶你破解...
    沈念sama閱讀 206,482評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異玷或,居然都是意外死亡儡首,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評論 2 382
  • 文/潘曉璐 我一進(jìn)店門偏友,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蔬胯,“玉大人,你說我怎么就攤上這事位他》毡簦” “怎么了?”我有些...
    開封第一講書人閱讀 152,762評論 0 342
  • 文/不壞的土叔 我叫張陵棱诱,是天一觀的道長泼橘。 經(jīng)常有香客問我,道長迈勋,這世上最難降的妖魔是什么炬灭? 我笑而不...
    開封第一講書人閱讀 55,273評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮靡菇,結(jié)果婚禮上重归,老公的妹妹穿的比我還像新娘。我一直安慰自己厦凤,他們只是感情好鼻吮,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,289評論 5 373
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著较鼓,像睡著了一般椎木。 火紅的嫁衣襯著肌膚如雪违柏。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,046評論 1 285
  • 那天香椎,我揣著相機(jī)與錄音漱竖,去河邊找鬼。 笑死畜伐,一個胖子當(dāng)著我的面吹牛馍惹,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播玛界,決...
    沈念sama閱讀 38,351評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼万矾,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了慎框?” 一聲冷哼從身側(cè)響起良狈,我...
    開封第一講書人閱讀 36,988評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎鲤脏,沒想到半個月后们颜,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體吕朵,經(jīng)...
    沈念sama閱讀 43,476評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡猎醇,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,948評論 2 324
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了努溃。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片硫嘶。...
    茶點(diǎn)故事閱讀 38,064評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖梧税,靈堂內(nèi)的尸體忽然破棺而出沦疾,到底是詐尸還是另有隱情,我是刑警寧澤第队,帶...
    沈念sama閱讀 33,712評論 4 323
  • 正文 年R本政府宣布哮塞,位于F島的核電站,受9級特大地震影響凳谦,放射性物質(zhì)發(fā)生泄漏忆畅。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,261評論 3 307
  • 文/蒙蒙 一尸执、第九天 我趴在偏房一處隱蔽的房頂上張望家凯。 院中可真熱鬧,春花似錦如失、人聲如沸绊诲。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽掂之。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間世舰,已是汗流浹背橄镜。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留冯乘,地道東北人洽胶。 一個月前我還...
    沈念sama閱讀 45,511評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像裆馒,于是被迫代替她去往敵國和親姊氓。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,802評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 個人認(rèn)為喷好,Goodboy1881先生的TCP /IP 協(xié)議詳解學(xué)習(xí)博客系列博客是一部非常精彩的學(xué)習(xí)筆記翔横,這雖然只是...
    貳零壹柒_fc10閱讀 5,051評論 0 8
  • 1.這篇文章不是本人原創(chuàng)的,只是個人為了對這部分知識做一個整理和系統(tǒng)的輸出而編輯成的梗搅,在此鄭重地向本文所引用文章的...
    SOMCENT閱讀 13,037評論 6 174
  • TCP問題分析 網(wǎng)絡(luò)的五層協(xié)議 物理層 數(shù)據(jù)鏈路層 網(wǎng)絡(luò)層禾唁,IP協(xié)議,ICMP協(xié)議(ping) 傳輸層无切,傳輸層有兩...
    大大大大大先生閱讀 10,760評論 0 6
  • 傳輸層-TCP荡短, TCP頭部結(jié)構(gòu) ,TCP序列號和確認(rèn)號詳解 TCP主要解決下面的三個問題 1.數(shù)據(jù)的可靠傳輸...
    抓兔子的貓閱讀 4,502評論 1 46
  • 我們用websocket和http來研究一下TCP/IP協(xié)議的一些特性哆键,在上一篇文章《https連接的前幾毫秒發(fā)生...
    極樂君閱讀 1,920評論 1 6