問題描述:在這幾年的Android開發(fā)中,遇到了一個(gè)困擾我好久的問題,有時(shí)候在公司的wifi下逢捺,請(qǐng)求我們的公司自己的服務(wù)器很慢,甚至經(jīng)常請(qǐng)求失敗癞季,切換成移動(dòng)網(wǎng)絡(luò)3G或者4G劫瞳,就明顯變快。but在相同的wifi環(huán)境下,用iphone和電腦請(qǐng)求就很快
剛開始發(fā)現(xiàn)手機(jī)wifi很慢的時(shí)候绷柒,以為是公司網(wǎng)絡(luò)的問題志于,所以找運(yùn)維去解決,運(yùn)維的解釋是我們公司用的北京鵬博士的寬帶废睦,公司機(jī)房是用的北京聯(lián)通的寬帶伺绽,公司的網(wǎng)絡(luò)連接公司的服務(wù)器要經(jīng)過武漢的轉(zhuǎn)接點(diǎn)才能連到公司的服務(wù)器,繞了一個(gè)大圈郊楣,導(dǎo)致請(qǐng)求變慢憔恳,解決方法是接入多個(gè)運(yùn)營商,但是由于公司預(yù)算的問題净蚤,這個(gè)沒法解決钥组。
后來發(fā)現(xiàn)只有Android手機(jī)連接服務(wù)器比較慢,iPhone和windows電腦請(qǐng)求都正常今瀑,我猜想可能是應(yīng)用的網(wǎng)絡(luò)請(qǐng)求框架有問題程梦,因此專門寫了一個(gè)demo,用Android提供的HttpUrlConnection直接請(qǐng)求点把,然后又用系統(tǒng)瀏覽器直接請(qǐng)求接口,也有同樣的問題屿附,排除了框架問題的可能郎逃。
難道是Android手機(jī)的wifi模塊質(zhì)量比較次,所以我把手頭所有Android手機(jī)都測(cè)試了一遍挺份,不管是貴的褒翰,還是便宜的,可能爆炸的還是工匠精神的都有此問題匀泊,并且還發(fā)現(xiàn)在家里的wifi下速度嗖嗖的优训。所以wifi模塊的問題也排除了。
后來又想難道是發(fā)送出去的數(shù)據(jù)有問題各聘,所以我就開始用Fiddler抓包揣非,然后發(fā)現(xiàn)只要通過代理,將App代理到公司電腦上躲因,在公司wifi下早敬,連接很順暢,后來又特意用手機(jī)做了一個(gè)熱點(diǎn)大脉,共享wifi到另一臺(tái)手機(jī)搞监,也很順暢/
至此,因?yàn)樗接邢尴溲ィ心茉嚨姆椒ǘ加昧讼俟洌瑳]有定位到原因,這個(gè)問題也就擱置了衡怀。后來有一天研究okhttp,看到復(fù)用連接池,突然想到會(huì)不會(huì)跟這個(gè)原因有關(guān)呢安疗,想要看連接有沒有被復(fù)用抛杨,就要開始對(duì)Android手機(jī)進(jìn)行抓包,并且不能通過代理的方式抓包荐类,要直接抓包怖现,抓包方法:http://blog.csdn.net/jk38687587/article/details/48467329
安裝好抓包工具后,開始對(duì)手機(jī)進(jìn)行抓包玉罐,通過和電腦直接請(qǐng)求的包進(jìn)行對(duì)比屈嗤,發(fā)現(xiàn)手機(jī)wifi下,Tcp Retransmission的情況很多,如圖所示
這是什么鬼吊输,SYN是什么玩意兒饶号,ACK是啥(黑人懵逼臉.jpg),好吧季蚂,先惡補(bǔ)一下TCP/IP協(xié)議茫船,然后谷歌一下琅束,說是在第一次握手(SYN)的時(shí)候網(wǎng)絡(luò)請(qǐng)求超時(shí)重發(fā),但是為什么會(huì)超時(shí)呢算谈,如果網(wǎng)絡(luò)不好為什么windows下的請(qǐng)求就不超時(shí)呢?再仔細(xì)對(duì)比兩邊發(fā)出去數(shù)據(jù)包涩禀,發(fā)現(xiàn)Android發(fā)出去的包比windows發(fā)出去的包多了個(gè)timestamps字段,查查這個(gè)是什么玩意兒然眼,查到了http://blog.csdn.net/jueshengtianya/article/details/50440696艾船,有可能時(shí)間戳可能會(huì)導(dǎo)致客戶端訪問不了服務(wù)器,有兩種解決方案高每,一種是將服務(wù)器的時(shí)間戳net.ipv4.tcp_timestamps設(shè)置為0丽声,另一種是該客戶端,將時(shí)間戳關(guān)閉觉义,服務(wù)器咱改不了雁社,先改改客戶端吧,客戶端怎么改呀晒骇,在尋找答案的過程中還發(fā)現(xiàn)了有人跟我遇到過同樣的問題Android之網(wǎng)絡(luò)丟包事件霉撵,我先試著用Root Explorer修改/proc/sys/net/ipv4文件夾下的tcp_timestamps文件(在這里遇到一個(gè)坑,以為可以直接編輯修改洪囤,廢了好大勁也沒修改成功徒坡,以為是root不徹底,鼓搗了半天root,也沒成功瘤缩,后來發(fā)現(xiàn)必須要通過命令才能修改喇完,詳見:http://blog.csdn.net/apn172/article/details/8034240)
先將timestamps設(shè)置為0,
抓包顯示
timestamps沒有了剥啤,效果立顯锦溪,所有的重發(fā)都沒有了
再設(shè)置回去:抓包顯示
問題又出現(xiàn)了,來回試了幾十遍府怯,確認(rèn)就是這個(gè)參數(shù)的問題刻诊。好有成就感呀。
但是這個(gè)問題最終的解決方案還得服務(wù)器改牺丙,因?yàn)榭蛻舳烁倪@個(gè)參數(shù)要root,所以經(jīng)過跟運(yùn)維的同學(xué)溝通则涯,將服務(wù)器的net.ipv4.tcp_timestamps設(shè)置為0和1,分別驗(yàn)證效果冲簿,結(jié)果很明顯粟判,就是這個(gè)參數(shù)的問題,最終服務(wù)器的同學(xué)將這個(gè)參數(shù)設(shè)置為了0峦剔,至此档礁,困擾了我好久的問題終于得到了解決!Q蛞臁事秀!
事后彤断,查了一下tcp_timestamps的相關(guān)資料,了解了一下RFC1323協(xié)議易迹,在linux中如果是tcp_tw_recycle被打開了話宰衙,會(huì)假設(shè)對(duì)端開啟了 tcp_timestamps,然后會(huì)去比較時(shí)間戳睹欲,如果時(shí)間戳變大了供炼,就可以重用。tcp_timestamps記錄的是從開機(jī)到現(xiàn)在所經(jīng)過的秒數(shù)窘疮,tcp_tw_recycle在開啟后會(huì)比較同一公網(wǎng)ip下的tcp_timestamps,所以在同一wifi下袋哼,在第一次SYN的時(shí)候,tcp_timestamps如果比其他設(shè)備的tcp_timestamps小的話闸衫,包就直接被丟棄涛贯。