Jack Jiang

          我的最新工程MobileIMSDK:http://git.oschina.net/jackjiang/MobileIMSDK
          posts - 499, comments - 13, trackbacks - 0, articles - 1

          本文原題“你管這破玩意兒叫TCP?”,由閃客sun分享,轉(zhuǎn)載請(qǐng)聯(lián)系作者。

          1、引言

          網(wǎng)絡(luò)編程能力對(duì)于即時(shí)通訊技術(shù)開(kāi)發(fā)者來(lái)說(shuō)是基本功,而計(jì)算機(jī)網(wǎng)絡(luò)又是網(wǎng)絡(luò)編程的理論根基,因而深刻準(zhǔn)確地理解計(jì)算機(jī)網(wǎng)絡(luò)知識(shí)顯然能夯實(shí)你的即時(shí)通訊應(yīng)用的實(shí)踐品質(zhì)。

          本文風(fēng)格類(lèi)似于《網(wǎng)絡(luò)編程懶人入門(mén)》、《腦殘式網(wǎng)絡(luò)編程入門(mén)》兩個(gè)系列,但通俗又不失內(nèi)涵,簡(jiǎn)潔又不簡(jiǎn)陋,非常適合對(duì)計(jì)算機(jī)網(wǎng)絡(luò)知識(shí)有向往但又有懼怕的網(wǎng)絡(luò)編程愛(ài)好者們閱讀,希望能給你帶來(lái)不一樣的網(wǎng)絡(luò)知識(shí)入門(mén)視角。

          本篇將運(yùn)用通俗易懂的語(yǔ)言,配上細(xì)致精確的圖片動(dòng)畫(huà),循序漸進(jìn)地引導(dǎo)你理解TCP協(xié)議的主要特性和技術(shù)原理,讓TCP協(xié)議的學(xué)習(xí)不再如此枯燥和生澀,非常適合入門(mén)者閱讀。

          本文已同步發(fā)布于“即時(shí)通訊技術(shù)圈”公眾號(hào),歡迎關(guān)注。公眾號(hào)上的鏈接是:點(diǎn)此進(jìn)入。

          2、系列文章

          本文是該系列文章中的第2篇:

          本文主要涉及計(jì)算機(jī)網(wǎng)絡(luò)的傳輸層,希望讓TCP協(xié)議的學(xué)習(xí)不再枯燥和生澀。

          3、初識(shí)傳輸層

          你是一臺(tái)電腦,你的名字叫 A。

          網(wǎng)絡(luò)編程入門(mén)從未如此簡(jiǎn)單(二):假如你來(lái)設(shè)計(jì)TCP協(xié)議,會(huì)怎么做?_1-1.png
          經(jīng)過(guò)上篇《假如你來(lái)設(shè)計(jì)網(wǎng)絡(luò),會(huì)怎么做?》的一番折騰,只要你知道另一位伙伴 B 的 IP 地址,且你們之間的網(wǎng)絡(luò)是通的,無(wú)論多遠(yuǎn),你都可以將一個(gè)數(shù)據(jù)包發(fā)送給你的伙伴 B。

          網(wǎng)絡(luò)編程入門(mén)從未如此簡(jiǎn)單(二):假如你來(lái)設(shè)計(jì)TCP協(xié)議,會(huì)怎么做?_1-2.png

          上篇中分享的這就是物理層、數(shù)據(jù)鏈路層、網(wǎng)絡(luò)層這三層所做的事情。

          站在第四層的你,就可以不要臉地利用下三層所做的鋪墊,隨心所欲地發(fā)送數(shù)據(jù),而不必?fù)?dān)心找不到對(duì)方了。

          網(wǎng)絡(luò)編程入門(mén)從未如此簡(jiǎn)單(二):假如你來(lái)設(shè)計(jì)TCP協(xié)議,會(huì)怎么做?_1-3.gif

          雖然你此時(shí)還什么都沒(méi)干,但你還是給自己這一層起了個(gè)響亮的名字,叫做傳輸層。

          你本以為自己所在的第四層萬(wàn)事大吉,啥事沒(méi)有,但很快問(wèn)題就接踵而至。

          4、問(wèn)題來(lái)了

          前三層協(xié)議只能把數(shù)據(jù)包從一個(gè)主機(jī)搬到另外一臺(tái)主機(jī),但是到了目的地以后,數(shù)據(jù)包具體交給哪個(gè)程序(進(jìn)程)呢?

          網(wǎng)絡(luò)編程入門(mén)從未如此簡(jiǎn)單(二):假如你來(lái)設(shè)計(jì)TCP協(xié)議,會(huì)怎么做?_2-1.png

          所以:你需要把通信的進(jìn)程區(qū)分開(kāi)來(lái),于是就給每個(gè)進(jìn)程分配一個(gè)數(shù)字編號(hào),你給它起了一個(gè)響亮的名字:端口號(hào)。

          網(wǎng)絡(luò)編程入門(mén)從未如此簡(jiǎn)單(二):假如你來(lái)設(shè)計(jì)TCP協(xié)議,會(huì)怎么做?_2-2.png

          然后:你在要發(fā)送的數(shù)據(jù)包上,增加了傳輸層的頭部:源端口號(hào)與目標(biāo)端口號(hào)。

          網(wǎng)絡(luò)編程入門(mén)從未如此簡(jiǎn)單(二):假如你來(lái)設(shè)計(jì)TCP協(xié)議,會(huì)怎么做?_2-3.png

          OK,這樣你將原本主機(jī)到主機(jī)的通信,升級(jí)為了進(jìn)程和進(jìn)程之間的通信。

          你沒(méi)有意識(shí)到,你不知不覺(jué)實(shí)現(xiàn)了UDP協(xié)議!

          當(dāng)然 UDP 協(xié)議中不光有源端口和目標(biāo)端口,還有數(shù)據(jù)包長(zhǎng)度和校驗(yàn)值,我們暫且略過(guò)。

          就這樣,你用 UDP 協(xié)議無(wú)憂(yōu)無(wú)慮地同 B 進(jìn)行著通信,一直沒(méi)發(fā)生什么問(wèn)題。

          網(wǎng)絡(luò)編程入門(mén)從未如此簡(jiǎn)單(二):假如你來(lái)設(shè)計(jì)TCP協(xié)議,會(huì)怎么做?_2-4.gif

          但很快,你發(fā)現(xiàn)事情變得非常復(fù)雜 ... ...

          5、丟包問(wèn)題

          由于網(wǎng)絡(luò)的不可靠,數(shù)據(jù)包可能在半路丟失,而 A 和 B 卻無(wú)法察覺(jué)。

          網(wǎng)絡(luò)編程入門(mén)從未如此簡(jiǎn)單(二):假如你來(lái)設(shè)計(jì)TCP協(xié)議,會(huì)怎么做?_3-1.gif

          對(duì)于丟包問(wèn)題,只要解決兩個(gè)事就好了。

          第一個(gè):A 怎么知道包丟了?
          答案是:讓 B 告訴 A。

          第二個(gè):丟了的包怎么辦?
          答案是:重傳。

          于是你設(shè)計(jì)了如下方案:A 每發(fā)一個(gè)包,都必須收到來(lái)自 B 的確認(rèn)(ACK),再發(fā)下一個(gè),否則在一定時(shí)間內(nèi)沒(méi)有收到確認(rèn),就重傳這個(gè)包。

          網(wǎng)絡(luò)編程入門(mén)從未如此簡(jiǎn)單(二):假如你來(lái)設(shè)計(jì)TCP協(xié)議,會(huì)怎么做?_3-2.gif

          你管它叫停止等待協(xié)議。

          只要按照這個(gè)協(xié)議來(lái),雖然 A 無(wú)法保證 B 一定能收到包,但 A 能夠確認(rèn) B 是否收到了包,收不到就重試,盡最大努力讓這個(gè)通信過(guò)程變得可靠,于是你們現(xiàn)在的通信過(guò)程又有了一個(gè)新的特征,可靠交付。

          6、效率問(wèn)題

          停止等待雖然能解決問(wèn)題,但是效率太低了。

          A 原本可以在發(fā)完第一個(gè)數(shù)據(jù)包之后立刻開(kāi)始發(fā)第二個(gè)數(shù)據(jù)包,但由于停止等待協(xié)議,A 必須等數(shù)據(jù)包到達(dá)了 B ,且 B 的 ACK 包又回到了 A,才可以繼續(xù)發(fā)第二個(gè)數(shù)據(jù)包。這效率慢得可不是一點(diǎn)兩點(diǎn)。

          于是:你對(duì)這個(gè)過(guò)程進(jìn)行了改進(jìn),采用流水線(xiàn)的方式,不再傻傻地等。

          網(wǎng)絡(luò)編程入門(mén)從未如此簡(jiǎn)單(二):假如你來(lái)設(shè)計(jì)TCP協(xié)議,會(huì)怎么做?_4-1.gif

          7、順序問(wèn)題

          但是網(wǎng)路是復(fù)雜的、不可靠的。

          這導(dǎo)致的問(wèn)題是:有的時(shí)候 A 發(fā)出去的數(shù)據(jù)包,分別走了不同的路由到達(dá) B,可能無(wú)法保證和發(fā)送數(shù)據(jù)包時(shí)一樣的順序。

          網(wǎng)絡(luò)編程入門(mén)從未如此簡(jiǎn)單(二):假如你來(lái)設(shè)計(jì)TCP協(xié)議,會(huì)怎么做?_5-1.gif

          對(duì)應(yīng)于我們的例子:在流水線(xiàn)中有多個(gè)數(shù)據(jù)包和ACK包在亂序流動(dòng),他們之間對(duì)應(yīng)關(guān)系就亂掉了。

          如果回到上面的停止等待協(xié)議,那么A 每收到一個(gè)包的確認(rèn)(ACK)再發(fā)下一個(gè)包,那就根本不存在順序問(wèn)題。但,應(yīng)該有更好的辦法吧?

          是的,更好的辦法就是:A 在發(fā)送的數(shù)據(jù)包中增加一個(gè)序號(hào)(seq),同時(shí) B 要在 ACK 包上增加一個(gè)確認(rèn)號(hào)(ack)。這樣不但解決了停止等待協(xié)議的效率問(wèn)題,也通過(guò)這樣標(biāo)序號(hào)的方式解決了順序問(wèn)題。

          網(wǎng)絡(luò)編程入門(mén)從未如此簡(jiǎn)單(二):假如你來(lái)設(shè)計(jì)TCP協(xié)議,會(huì)怎么做?_5-2.gif

          而 B 這個(gè)確認(rèn)號(hào)意味深長(zhǎng):比如 B 發(fā)了一個(gè)確認(rèn)號(hào)為 ack = 3,它不僅僅表示 A 發(fā)送的序號(hào)為 2 的包收到了,還表示 2 之前的數(shù)據(jù)包都收到了。這種方式叫累計(jì)確認(rèn)累計(jì)應(yīng)答

          網(wǎng)絡(luò)編程入門(mén)從未如此簡(jiǎn)單(二):假如你來(lái)設(shè)計(jì)TCP協(xié)議,會(huì)怎么做?_5-3.gif

          注意:實(shí)際上 ack 的號(hào)是收到的最后一個(gè)數(shù)據(jù)包的序號(hào) seq + 1,也就是告訴對(duì)方下一個(gè)應(yīng)該發(fā)的序號(hào)是多少。但圖中為了便于理解,ack 就表示收到的那個(gè)序號(hào),不必糾結(jié)。

          8、流量問(wèn)題

          有的時(shí)候,A 發(fā)送數(shù)據(jù)包的速度太快,而 B 的接收能力不夠,但 B 卻沒(méi)有告知 A 這個(gè)情況。

          網(wǎng)絡(luò)編程入門(mén)從未如此簡(jiǎn)單(二):假如你來(lái)設(shè)計(jì)TCP協(xié)議,會(huì)怎么做?_6-1.gif

          怎么解決呢?

          很簡(jiǎn)單:B 告訴 A 自己的接收能力,A 根據(jù) B 的接收能力,相應(yīng)控制自己的發(fā)送速率就好了。

          B 怎么告訴 A 呢?B 跟 A 說(shuō)"我很強(qiáng)"這三個(gè)字么?那肯定不行,得有一個(gè)嚴(yán)謹(jǐn)?shù)囊?guī)范。

          于是 B 決定:每次發(fā)送數(shù)據(jù)包給 A 時(shí),順帶傳過(guò)來(lái)一個(gè)值,叫窗口大小(win),這個(gè)值就表示 B 的接收能力

          同理:每次 A 給 B 發(fā)包時(shí)也帶上自己的窗口大小,表示 A 的接收能力。

          網(wǎng)絡(luò)編程入門(mén)從未如此簡(jiǎn)單(二):假如你來(lái)設(shè)計(jì)TCP協(xié)議,會(huì)怎么做?_6-2.gif

          B 告訴了 A 自己的窗口大小值,A 怎么利用它去做 A 這邊發(fā)包的流量控制呢?

          很簡(jiǎn)單:假如 B 給 A 傳過(guò)來(lái)的窗口大小 win = 5,那 A 根據(jù)這個(gè)值,把自己要發(fā)送的數(shù)據(jù)分成這么幾類(lèi)。

          網(wǎng)絡(luò)編程入門(mén)從未如此簡(jiǎn)單(二):假如你來(lái)設(shè)計(jì)TCP協(xié)議,會(huì)怎么做?_6-3.png

          圖片過(guò)于清晰,就不再文字解釋了。

          當(dāng) A 不斷發(fā)送數(shù)據(jù)包時(shí),已發(fā)送的最后一個(gè)序號(hào)就往右移動(dòng),直到碰到了窗口的上邊界,此時(shí) A 就無(wú)法繼續(xù)發(fā)包,達(dá)到了流量控制。

          網(wǎng)絡(luò)編程入門(mén)從未如此簡(jiǎn)單(二):假如你來(lái)設(shè)計(jì)TCP協(xié)議,會(huì)怎么做?_6-4.gif

          但是:當(dāng) A 不斷發(fā)包的同時(shí),A 也會(huì)收到來(lái)自 B 的確認(rèn)包,此時(shí)整個(gè)窗口會(huì)往右移動(dòng),因此上邊界也往右移動(dòng),A 就能發(fā)更多的數(shù)據(jù)包了。

          網(wǎng)絡(luò)編程入門(mén)從未如此簡(jiǎn)單(二):假如你來(lái)設(shè)計(jì)TCP協(xié)議,會(huì)怎么做?_6-5.gif

          以上都是在窗口大小不變的情況下。而 B 在發(fā)給 A 的 ACK 包中,每一個(gè)都可以重新設(shè)置一個(gè)新的窗口大小,如果 A 收到了一個(gè)新的窗口大小值,A 會(huì)隨之調(diào)整。

          如果 A 收到了比原窗口值更大的窗口大小,比如 win = 6,則 A 會(huì)直接將窗口上邊界向右移動(dòng) 1 個(gè)單位。

          網(wǎng)絡(luò)編程入門(mén)從未如此簡(jiǎn)單(二):假如你來(lái)設(shè)計(jì)TCP協(xié)議,會(huì)怎么做?_6-6.gif

          如果 A 收到了比原窗口值小的窗口大小,比如 win = 4,則 A 暫時(shí)不會(huì)改變窗口大小,更不會(huì)將窗口上邊界向左移動(dòng),而是等著 ACK 的到來(lái),不斷將左邊界向右移動(dòng),直到窗口大小值收縮到新大小為止。

          網(wǎng)絡(luò)編程入門(mén)從未如此簡(jiǎn)單(二):假如你來(lái)設(shè)計(jì)TCP協(xié)議,會(huì)怎么做?_6-7.gif

          OK,終于將流量控制問(wèn)題解決得差不多了,你看著上面一個(gè)個(gè)小動(dòng)圖,給這個(gè)窗口起了一個(gè)更生動(dòng)的名字:滑動(dòng)窗口。

          9、擁塞問(wèn)題

          但有的時(shí)候,不是 B 的接受能力不夠,而是網(wǎng)絡(luò)不太好,造成了網(wǎng)絡(luò)擁塞。

          網(wǎng)絡(luò)編程入門(mén)從未如此簡(jiǎn)單(二):假如你來(lái)設(shè)計(jì)TCP協(xié)議,會(huì)怎么做?_7-1.gif

          擁塞控制與流量控制有些像,但流量控制是受 B 的接收能力影響,而擁塞控制是受網(wǎng)絡(luò)環(huán)境的影響。

          擁塞控制的解決辦法依然是通過(guò)設(shè)置一定的窗口大小。只不過(guò),流量控制的窗口大小是 B 直接告訴 A 的,而擁塞控制的窗口大小按理說(shuō)就應(yīng)該是網(wǎng)絡(luò)環(huán)境主動(dòng)告訴 A。

          但網(wǎng)絡(luò)環(huán)境怎么可能主動(dòng)告訴 A 呢?只能 A 單方面通過(guò)試探,不斷感知網(wǎng)絡(luò)環(huán)境的好壞,進(jìn)而確定自己的擁塞窗口的大小。

          網(wǎng)絡(luò)編程入門(mén)從未如此簡(jiǎn)單(二):假如你來(lái)設(shè)計(jì)TCP協(xié)議,會(huì)怎么做?_7-2.gif

          擁塞窗口大小的計(jì)算有很多復(fù)雜的算法,就不在本文中展開(kāi)了(有興趣可以深入閱讀《[通俗易懂]深入理解TCP協(xié)議(下):RTT、滑動(dòng)窗口、擁塞處理》)。

          假如擁塞窗口的大小為  cwnd,上一部分流量控制的滑動(dòng)窗口的大小為 rwnd,那么窗口的右邊界受這兩個(gè)值共同的影響,需要取它倆的最小值。

          窗口大小 = min(cwnd, rwnd)

          含義很容易理解:當(dāng) B 的接受能力比較差時(shí),即使網(wǎng)絡(luò)非常通暢,A 也需要根據(jù) B 的接收能力限制自己的發(fā)送窗口。當(dāng)網(wǎng)絡(luò)環(huán)境比較差時(shí),即使 B 有很強(qiáng)的接收能力,A 也要根據(jù)網(wǎng)絡(luò)的擁塞情況來(lái)限制自己的發(fā)送窗口。正所謂受其短板的影響嘛~

          10、連接問(wèn)題

          有的時(shí)候,B 主機(jī)的相應(yīng)進(jìn)程還沒(méi)有準(zhǔn)備好或是掛掉了,A 就開(kāi)始發(fā)送數(shù)據(jù)包,導(dǎo)致了浪費(fèi)。

          網(wǎng)絡(luò)編程入門(mén)從未如此簡(jiǎn)單(二):假如你來(lái)設(shè)計(jì)TCP協(xié)議,會(huì)怎么做?_8-1.gif

          這個(gè)問(wèn)題在于:A 在跟 B 通信之前,沒(méi)有事先確認(rèn) B 是否已經(jīng)準(zhǔn)備好,就開(kāi)始發(fā)了一連串的信息。就好比你和另一個(gè)人打電話(huà),你還沒(méi)有"喂"一下確認(rèn)對(duì)方有沒(méi)有在聽(tīng),你就巴拉巴拉說(shuō)了一堆。

          這個(gè)問(wèn)題該怎么解決呢?

          地球人都知道:三次握手嘛!

          • A:我準(zhǔn)備好了(SYN)
          • B:我知道了(ACK),我也準(zhǔn)備好了(SYN)
          • A:我知道了(ACK)

          網(wǎng)絡(luò)編程入門(mén)從未如此簡(jiǎn)單(二):假如你來(lái)設(shè)計(jì)TCP協(xié)議,會(huì)怎么做?_8-2.gif

          A 與 B 各自在內(nèi)存中維護(hù)著自己的狀態(tài)變量,三次握手之后,雙方的狀態(tài)都變成了連接已建立(ESTABLISHED)。

          雖然就只是發(fā)了三次數(shù)據(jù)包,并且在各自的內(nèi)存中維護(hù)了狀態(tài)變量,但這么說(shuō)總覺(jué)得太 low,你看這個(gè)過(guò)程相當(dāng)于雙方建立連接的過(guò)程,于是你靈機(jī)一動(dòng),就叫它面向連接吧。

          注意:這個(gè)連接是虛擬的,是由 A 和 B 這兩個(gè)終端共同維護(hù)的,在網(wǎng)絡(luò)中的設(shè)備根本就不知道連接這回事兒!

          但凡事有始就有終,有了建立連接的過(guò)程,就要考慮釋放連接的過(guò)程。

          這就是網(wǎng)絡(luò)編程中耳熟能詳?shù)乃拇螕]手啦!

          • A:再見(jiàn),我要關(guān)閉了(FIN)
          • B:我知道了(ACK)。給 B 一段時(shí)間把自己的事情處理完...
          • B:再見(jiàn),我要關(guān)閉了(FIN)
          • A:我知道了(ACK)

          網(wǎng)絡(luò)編程入門(mén)從未如此簡(jiǎn)單(二):假如你來(lái)設(shè)計(jì)TCP協(xié)議,會(huì)怎么做?_8-3.gif

          11、小結(jié)一下

          以上講述的,就是 TCP 協(xié)議的核心思想,上面過(guò)程中需要傳輸?shù)男畔ⅲ腕w現(xiàn)在 TCP 協(xié)議的頭部,這里放上最常見(jiàn)的 TCP 協(xié)議頭解讀的圖。

          網(wǎng)絡(luò)編程入門(mén)從未如此簡(jiǎn)單(二):假如你來(lái)設(shè)計(jì)TCP協(xié)議,會(huì)怎么做?_9-1.png

          不知道你現(xiàn)在再看下面這句話(huà),是否能理解:

          TCP 是面向連接的、可靠的、基于字節(jié)流的傳輸層通信協(xié)議。

          “面向連接、可靠”,這兩個(gè)詞通過(guò)上面的講述很容易理解,那什么叫做基于字節(jié)流呢?

          很簡(jiǎn)單:TCP 在建立連接時(shí),需要告訴對(duì)方 MSS(最大報(bào)文段大?。?。

          也就是說(shuō):如果要發(fā)送的數(shù)據(jù)很大,在 TCP 層是需要按照 MSS 來(lái)切割成一個(gè)個(gè)的 TCP 報(bào)文段 的。

          切割的時(shí)候我才不管你原來(lái)的數(shù)據(jù)表示什么意思,需要在哪里斷句啥的,我就把它當(dāng)成一串毫無(wú)意義的字節(jié),在我想要切割的地方咔嚓就來(lái)一刀,標(biāo)上序號(hào),只要接收方再根據(jù)這個(gè)序號(hào)拼成最終想要的完整數(shù)據(jù)就行了。

          在我 TCP 傳輸這里,我就把它當(dāng)做一個(gè)個(gè)的字節(jié),也就是基于字節(jié)流的含義了。

          網(wǎng)絡(luò)編程入門(mén)從未如此簡(jiǎn)單(二):假如你來(lái)設(shè)計(jì)TCP協(xié)議,會(huì)怎么做?_10-1.png

          12、寫(xiě)在最后

          一提到 TCP,可能很多人都想起被三次握手和四次揮手所支配的恐懼。

          但其實(shí)你跟著本文中的思路你就會(huì)發(fā)現(xiàn),三次握手與四次揮手只占 TCP 所解決的核心問(wèn)題中很小的一部分,只是因?yàn)樗诿嬖囍泻苓m合作為知識(shí)點(diǎn)進(jìn)行考察,所以在很多人的印象中就好像 TCP 的核心就是握手和揮手似的。

          本文希望你能從問(wèn)題出發(fā),真正理解 TCP 所想要解決的問(wèn)題,你會(huì)發(fā)現(xiàn)很多原理就好像生活常識(shí)一樣順其自然,并不復(fù)雜,希望你有收獲~

          最后,如果對(duì)TCP的理解仍存在疑惑,可以繼續(xù)閱讀以下精選的資料:

          本文已同步發(fā)布于“即時(shí)通訊技術(shù)圈”公眾號(hào)。

          ▲ 本文在公眾號(hào)上的鏈接是:點(diǎn)此進(jìn)入。同步發(fā)布鏈接是:http://www.52im.net/thread-3339-1-1.html



          作者:Jack Jiang (點(diǎn)擊作者姓名進(jìn)入Github)
          出處:http://www.52im.net/space-uid-1.html
          交流:歡迎加入即時(shí)通訊開(kāi)發(fā)交流群 215891622
          討論:http://www.52im.net/
          Jack Jiang同時(shí)是【原創(chuàng)Java Swing外觀工程BeautyEye】【輕量級(jí)移動(dòng)端即時(shí)通訊框架MobileIMSDK】的作者,可前往下載交流。
          本博文 歡迎轉(zhuǎn)載,轉(zhuǎn)載請(qǐng)注明出處(也可前往 我的52im.net 找到我)。


          只有注冊(cè)用戶(hù)登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          Jack Jiang的 Mail: jb2011@163.com, 聯(lián)系QQ: 413980957, 微信: hellojackjiang
          主站蜘蛛池模板: 克东县| 博兴县| 苍南县| 青田县| 平定县| 昂仁县| 保德县| 合山市| 鹤岗市| 休宁县| 自治县| 舟曲县| 阳高县| 襄樊市| 潮安县| 中山市| 荥阳市| 平湖市| 山阴县| 平顺县| 阆中市| 南阳市| 天峨县| 松溪县| 长宁区| 得荣县| 太和县| 炉霍县| 顺昌县| 凭祥市| 太保市| 获嘉县| 黄大仙区| 晋宁县| 扶余县| 新野县| 岳阳市| 即墨市| 西平县| 惠州市| 龙山县|