主目錄見: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)的
TCP協(xié)議
-
TCP協(xié)議的Header組成迎罗,TCP協(xié)議首部箩退,如果除去Options(選項(xiàng))的長度,有20個字節(jié)長度佳谦,IP協(xié)議首部也有20個字節(jié)的長度
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四次揮手
和三次握手比較類似躬存,主機(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算法
這個是未用Nagle算法的抓包信息
滑動窗口
對于發(fā)送方來說:
- 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ù)
- Send But Not Yet Acknowledged:這部分?jǐn)?shù)據(jù)稱為發(fā)送但沒有被確認(rèn)鹉梨,數(shù)據(jù)被發(fā)送出去闺魏,沒有收到接收端的ACK,認(rèn)為并沒有完成發(fā)送俯画,這個屬于窗口內(nèi)的數(shù)據(jù)
- Not Sent析桥,Recipient Ready to Receive:這部分是盡快發(fā)送的數(shù)據(jù),這部分?jǐn)?shù)據(jù)已經(jīng)被加載到緩存中艰垂,也就是窗口中了泡仗,等待發(fā)送,其實(shí)這個窗口是完全有接收方告知的猜憎,接收方告知還是能夠接受這些包娩怎,所以發(fā)送方需要盡快的發(fā)送這些包
- Not Sent,Recipient Not Ready to Receive: 這些數(shù)據(jù)屬于未發(fā)送胰柑,同時接收端也不允許發(fā)送的截亦,因?yàn)檫@些數(shù)據(jù)已經(jīng)超出了發(fā)送端所接收的范圍
對于接收方來說:
- Received and ACK Not Send to Process:這部分?jǐn)?shù)據(jù)屬于接收了數(shù)據(jù)但是還沒有被上層的應(yīng)用程序接收,也是被緩存在窗口內(nèi)
- Received Not ACK: 已經(jīng)接收柬讨,但是還沒有回復(fù)ACK崩瓤,這些包可能輸屬于Delay ACK的范疇了
- Not Received:有空位,還沒有被接收的數(shù)據(jù)
窗口的動態(tài)調(diào)整:
- 客戶端給服務(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)超時異常
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秒酒来,具體抓包信息如下:
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衡奥,分配策略如下:
- 自動分配方式(Automatic Allocation)爹袁,DHCP服務(wù)器為主機(jī)指定一個永久性的IP地址,一旦DHCP客戶端第一次成功從DHCP服務(wù)器端租用到IP地址后矮固,就可以永久性的使用該地址
- 動態(tài)分配方式(Dynamic Allocation)失息,DHCP服務(wù)器給主機(jī)指定一個具有時間限制的IP地址,時間到期或主機(jī)明確表示放棄該地址時档址,該地址可以被其他主機(jī)使用
- 手工分配方式(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.
應(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擁塞窗口線性增加)
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是接收到對方消息的時間戳