惡補(bǔ)TCP --- 基礎(chǔ)

預(yù)備知識

TCP 頭格式


Screen Shot 2017-05-22 at 9.23.09 PM.png

截圖來源

TCP的包是沒有IP地址的,那是IP層上的事哈垢。但是有源端口和目標(biāo)端口槽卫。
一個TCP連接需要四個元組來表示是同一個連接(src_ip, src_port, dst_ip, dst_port)準(zhǔn)確說是五元組菠净,還有一個是協(xié)議甘改。但因為這里只是說TCP協(xié)議呛凶,所以男娄,這里我只說四元組。

注意上圖中的四個非常重要的東西:

  • Sequence Number是包的序號把兔,用來解決網(wǎng)絡(luò)包亂序(reordering)問題沪伙。
  • Acknowledgement Number就是ACK——用于確認(rèn)收到,用來解決不丟包的問題县好。
  • Window又叫Advertised-Window围橡,也就是著名的滑動窗口(Sliding Window),用于解決流控的缕贡。
  • TCP Flag 翁授,也就是包的類型,主要是用于操控TCP的狀態(tài)機(jī)的晾咪。

TCP 特點

  • 三次握手
  • 四次揮手
  • 可靠連接
  • 丟包重傳
  • TCP連接狀態(tài)

TCP的一個核心是:可靠傳輸協(xié)議收擦。

三次握手

  • 第一步:client 發(fā)送 syn 到server 發(fā)起握手;
  • 第二步:server 收到 syn后回復(fù)syn+ack給client谍倦;
  • 第三步:client 收到syn+ack后塞赂,回復(fù)server一個ack表示收到了server的syn+ack。

ack總是seq+len(包的大兄缰)宴猾,這樣發(fā)送方明確知道server收到那些東西了,但是特例是三次握手和四次揮手叼旋,雖然len都是0仇哆,但是syn和fin都要占用一個seq號,所以這里的ack都是seq+1夫植。

tcp在傳輸過程中都有一個ack讹剔,接收方通過ack告訴發(fā)送方收到那些包了。這樣發(fā)送方能知道有沒有丟包详民,進(jìn)而確定重傳

  • 關(guān)于ISN的初始化延欠。ISN是不能hard code的,不然會出問題的——比如:如果連接建好后始終用1來做ISN阐斜,如果client發(fā)了30個segment過去衫冻,但是網(wǎng)絡(luò)斷了,于是 client重連谒出,又用了1做ISN隅俘,但是之前連接的那些包到了邻奠,于是就被當(dāng)成了新連接的包,此時为居,client的Sequence Number 可能是3床蜘,而Server端認(rèn)為client端的這個號是30了钢猛。全亂了执庐。RFC793中說榴啸,ISN會和一個假的時鐘綁在一起,這個時鐘會在每4微秒對ISN做加一操作膳凝,直到超過2^32碑隆,又從0開始。這樣蹬音,一個ISN的周期大約是4.55個小時上煤。因為,我們假設(shè)我們的TCP Segment在網(wǎng)絡(luò)上的存活時間不會超過Maximum Segment Lifetime(縮寫為MSL - Wikipedia語條)著淆,所以劫狠,只要MSL的值小于4.55小時,那么永部,我們就不會重用到ISN独泞。
  • 關(guān)于建連接時SYN超時。試想一下苔埋,如果server端接到了clien發(fā)的SYN后回了SYN-ACK后client掉線了懦砂,server端沒有收到client回來的ACK,那么组橄,這個連接處于一個中間狀態(tài)孕惜,即沒成功,也沒失敗晨炕。于是,server端如果在一定時間內(nèi)沒有收到的TCP會重發(fā)SYN-ACK毫炉。在Linux下瓮栗,默認(rèn)重試次數(shù)為5次,重試的間隔時間從1s開始每次都翻售瞄勾,5次的重試時間間隔為1s, 2s, 4s, 8s, 16s费奸,總共31s,第5次發(fā)出后還要等32s都知道第5次也超時了进陡,所以愿阐,總共需要 1s + 2s + 4s+ 8s+ 16s + 32s = 2^6 -1 = 63s,TCP才會把斷開這個連接趾疚。

當(dāng)len 不為0 時候缨历,Client 和Server是這樣保證數(shù)據(jù)傳輸?shù)摹?/p>

Seq的增加是和傳輸?shù)淖止?jié)數(shù)相關(guān)的以蕴。上圖中,三次握手后辛孵,先來了一個len:43的包丛肮,Server返回的ack=seq(Client):1000 + len:43 = 1043。表示服務(wù)器收到第一個數(shù)據(jù)包魄缚。TCP依靠Seq 和Ack 宝与,保障了TCP傳輸數(shù)據(jù)包的完整性。

四次揮手

因為TCP是全雙工的冶匹,所以习劫,發(fā)送方和接收方都需要Fin和Ack。 ?簡單說來是 “先關(guān)讀嚼隘,后關(guān)寫”诽里,一共需要四個階段。以CLIENT發(fā)起關(guān)閉連接為例:

  • 服務(wù)器讀通道關(guān)閉? : client主動發(fā)送Fin包給server
  • 客戶機(jī)寫通道關(guān)閉? : server回復(fù)Ack(對應(yīng)第一步fin包的ack)給client嗓蘑,表示server知道client要斷開了
  • 客戶機(jī)讀通道關(guān)閉? : server發(fā)送Fin包給client须肆,表示server也可以斷開了
  • 服務(wù)器寫通道關(guān)閉 :client回復(fù)Ack給server。

丟包重傳

重傳這部分完全摘抄自TCP 的那些事兒(上) 桩皿,總結(jié)實在太好了豌汇!

TCP要保證所有的數(shù)據(jù)包都可以到達(dá),所以泄隔,必需要有重傳機(jī)制拒贱。
注意佛嬉,接收端給發(fā)送端的Ack確認(rèn)只會確認(rèn)最后一個連續(xù)的包逻澳,比如,發(fā)送端發(fā)了1,2,3,4,5一共五份數(shù)據(jù)暖呕,接收端收到了1斜做,2,于是回ack 3湾揽,然后收到了4(注意此時3沒收到)瓤逼,此時的TCP會怎么辦?我們要知道库物,因為正如前面所說的霸旗,SeqNum和Ack是以字節(jié)數(shù)為單位,所以ack的時候戚揭,不能跳著確認(rèn)诱告,只能確認(rèn)最大的連續(xù)收到的包,不然民晒,發(fā)送端就以為之前的都收到了精居。

超時重傳機(jī)制
一種是不回ack锄禽,死等3,當(dāng)發(fā)送方發(fā)現(xiàn)收不到3的ack超時后箱蟆,會重傳3沟绪。一旦接收方收到3后,會ack 回 4——意味著3和4都收到了空猜。
但是绽慈,這種方式會有比較嚴(yán)重的問題,那就是因為要死等3辈毯,所以會導(dǎo)致4和5即便已經(jīng)收到了坝疼,而發(fā)送方也完全不知道發(fā)生了什么事,因為沒有收到Ack谆沃,所以钝凶,發(fā)送方可能會悲觀地認(rèn)為也丟了,所以有可能也會導(dǎo)致4和5的重傳唁影。
對此有兩種選擇:

  • 一種是僅重傳timeout的包耕陷。也就是第3份數(shù)據(jù)。
  • 另一種是重傳timeout后所有的數(shù)據(jù)据沈,也就是第3哟沫,4,5這三份數(shù)據(jù)锌介。

*這兩種方式有好也有不好嗜诀。第一種會節(jié)省帶寬,但是慢孔祸,第二種會快一點隆敢,但是會浪費帶寬,也可能會有無用功崔慧。但總體來說都不好拂蝎。因為都在等timeout,timeout可能會很長(在下篇會說TCP是怎么動態(tài)地計算出timeout的)
快速重傳機(jī)制

Fast Retransmit

于是惶室,TCP引入了一種叫Fast Retransmit 的算法匣屡,不以時間驅(qū)動,而以數(shù)據(jù)驅(qū)動重傳拇涤。也就是說,如果誉结,包沒有連續(xù)到達(dá)鹅士,就ack最后那個可能被丟了的包,如果發(fā)送方連續(xù)收到3次相同的ack惩坑,就重傳掉盅。Fast Retransmit的好處是不用等timeout了再重傳也拜。
比如:如果發(fā)送方發(fā)出了1,2趾痘,3慢哈,4,5份數(shù)據(jù)永票,第一份先到送了卵贱,于是就ack回2,結(jié)果2因為某些原因沒收到侣集,3到達(dá)了键俱,于是還是ack回2,后面的4和5都到了世分,但是還是ack回2编振,因為2還是沒有收到,于是發(fā)送端收到了三個ack=2的確認(rèn)臭埋,知道了2還沒有到踪央,于是就馬上重轉(zhuǎn)2。然后瓢阴,接收端收到了2畅蹂,此時因為3,4炫掐,5都收到了魁莉,于是ack回6。示意圖如下:

Fast Retransmit只解決了一個問題募胃,就是timeout的問題旗唁,它依然面臨一個艱難的選擇,就是痹束,是重傳之前的一個還是重傳所有的問題检疫。對于上面的示例來說,是重傳#2呢還是重傳#2祷嘶,#3屎媳,#4,#5呢论巍?因為發(fā)送端并不清楚這連續(xù)的3個ack(2)是誰傳回來的烛谊?也許發(fā)送端發(fā)了20份數(shù)據(jù),是#6嘉汰,#10丹禀,#20傳來的呢。這樣,發(fā)送端很有可能要重傳從2到20的這堆數(shù)據(jù)(這就是某些TCP的實際的實現(xiàn))双泪〕炙眩可見,這是一把雙刃劍焙矛。

SACK 方法

另外一種更好的方式叫:Selective Acknowledgment (SACK)(參看RFC 2018)葫盼,這種方式需要在TCP頭里加一個SACK的東西,ACK還是Fast Retransmit的ACK村斟,SACK則是匯報收到的數(shù)據(jù)碎版贫导。參看下圖:


這樣,在發(fā)送端就可以根據(jù)回傳的SACK來知道哪些數(shù)據(jù)到了邓梅,哪些沒有到脱盲。于是就優(yōu)化了Fast Retransmit的算法。當(dāng)然日缨,這個協(xié)議需要兩邊都支持钱反。在 Linux下,可以通過tcp_sack參數(shù)打開這個功能(Linux 2.4后默認(rèn)打開)匣距。
這里還需要注意一個問題——接收方Reneging面哥,所謂Reneging的意思就是接收方有權(quán)把已經(jīng)報給發(fā)送端SACK里的數(shù)據(jù)給丟了。這樣干是不被鼓勵的毅待,因為這個事會把問題復(fù)雜化了尚卫,但是,接收方這么做可能會有些極端情況尸红,比如要把內(nèi)存給別的更重要的東西吱涉。所以,發(fā)送方也不能完全依賴SACK外里,還是要依賴ACK怎爵,并維護(hù)Time-Out,如果后續(xù)的ACK沒有增長盅蝗,那么還是要把SACK的東西重傳鳖链,另外,接收端這邊永遠(yuǎn)不能把SACK的包標(biāo)記為Ack墩莫。

注意:SACK會消費發(fā)送方的資源芙委,試想,如果一個攻擊者給數(shù)據(jù)發(fā)送方發(fā)一堆SACK的選項狂秦,這會導(dǎo)致發(fā)送方開始要重傳甚至遍歷已經(jīng)發(fā)出的數(shù)據(jù)灌侣,這會消耗很多發(fā)送端的資源。詳細(xì)的東西請參看《TCP SACK的性能權(quán)衡

Duplicate SACK – 重復(fù)收到數(shù)據(jù)的問題
Duplicate SACK又稱D-SACK裂问,其主要使用了SACK來告訴發(fā)送方有哪些數(shù)據(jù)被重復(fù)接收了侧啼。RFC-2883 里有詳細(xì)描述和示例玖姑。下面舉幾個例子(來源于RFC-2883
D-SACK使用了SACK的第一個段來做標(biāo)志,
如果SACK的第一個段的范圍被ACK所覆蓋慨菱,那么就是D-SACK

如果SACK的第一個段的范圍被SACK的第二個段覆蓋,那么就是D-SACK

示例一:ACK丟包
下面的示例中戴甩,丟了兩個ACK符喝,所以,發(fā)送端重傳了第一個數(shù)據(jù)包(3000-3499)甜孤,于是接收端發(fā)現(xiàn)重復(fù)收到协饲,于是回了一個SACK=3000-3500,因為ACK都到了4000意味著收到了4000之前的所有數(shù)據(jù)缴川,所以這個SACK就是D-SACK——旨在告訴發(fā)送端我收到了重復(fù)的數(shù)據(jù)茉稠,而且我們的發(fā)送端還知道,數(shù)據(jù)包沒有丟把夸,丟的是ACK包而线。

Transmitted  Received    ACK Sent
Segment      Segment     (Including SACK Blocks)
 
3000-3499    3000-3499   3500 (ACK dropped)
3500-3999    3500-3999   4000 (ACK dropped)
3000-3499    3000-3499   4000, SACK=3000-3500

** 示例二,網(wǎng)絡(luò)延誤**
下面的示例中恋日,網(wǎng)絡(luò)包(1000-1499)被網(wǎng)絡(luò)給延誤了膀篮,導(dǎo)致發(fā)送方?jīng)]有收到ACK,而后面到達(dá)的三個包觸發(fā)了“Fast Retransmit算法”岂膳,所以重傳誓竿,但重傳時,被延誤的包又到了谈截,所以筷屡,回了一個SACK=1000-1500,因為ACK已到了3000簸喂,所以毙死,這個SACK是D-SACK——標(biāo)識收到了重復(fù)的包。
這個案例下娘赴,發(fā)送端知道之前因為“Fast Retransmit算法”觸發(fā)的重傳不是因為發(fā)出去的包丟了规哲,也不是因為回應(yīng)的ACK包丟了,而是因為網(wǎng)絡(luò)延時了诽表。

Transmitted    Received    ACK Sent
Segment        Segment     (Including SACK Blocks)
 
500-999        500-999     1000
1000-1499      (delayed)
1500-1999      1500-1999   1000, SACK=1500-2000
2000-2499      2000-2499   1000, SACK=1500-2500
2500-2999      2500-2999   1000, SACK=1500-3000
1000-1499      1000-1499   3000
1000-1499   3000, SACK=1000-1500

可見唉锌,引入了D-SACK,有這么幾個好處:
1)可以讓發(fā)送方知道竿奏,是發(fā)出去的包丟了袄简,還是回來的ACK包丟了。
2)是不是自己的timeout太小了泛啸,導(dǎo)致重傳绿语。
3)網(wǎng)絡(luò)上出現(xiàn)了先發(fā)的包后到的情況(又稱reordering)
4)網(wǎng)絡(luò)上是不是把我的數(shù)據(jù)包給復(fù)制了。
知道這些東西可以很好得幫助TCP了解網(wǎng)絡(luò)情況,從而可以更好的做網(wǎng)絡(luò)上的流控吕粹。

TCP連接狀態(tài)

Screen Shot 2017-05-22 at 10.56.20 PM.png
Screen Shot 2017-05-22 at 10.56.51 PM.png

圖片來源自TCP網(wǎng)絡(luò)關(guān)閉的狀態(tài)變換時序圖

建立連接

  • 正常情況
    1.1 S調(diào)用listen開啟監(jiān)聽种柑,S的狀態(tài)由CLOSED--->LISTEN。
    1.2 C調(diào)用connect發(fā)起連接匹耕,即發(fā)送SYN_1給S聚请,C的狀態(tài)由CLOSED---->SYN_SENT。

1.3 S收到SYN_1稳其,把此連接信息放入未完成連接隊列(incomplete connection queue)驶赏,回復(fù)SYN_2和ACK_1(SYN_1 + 1),S的狀態(tài)由LISTEN--->SYN_RCVD
1.4 C收到ACK_1和SYN_2既鞠,回復(fù)ACK_2(SYN_2 + 1)煤傍,C的狀態(tài)由SYN_SEND--->ESTABLISHED。
1.5 S收到ACK_2嘱蛋,把此連接信息從未完成連接隊列移除蚯姆,并放入完成連接隊列(complete connection queue),由listen函數(shù)的backlog控制完成連接隊列大小浑槽。S的狀態(tài)由SYN_RCVD--->ESTABLISHED蒋失。
1.6 S可以調(diào)用accept從完成連接隊列獲取已建立好的連接。

  • 同時建立連接
    2.1 S1和S2同時發(fā)送SYN(其中S1發(fā)送SYN_1桐玻,S2發(fā)送SYN_2)篙挽,S1和S2同時由LISTEN--->SYN_SENT。
    2.2 S1收到SYN_2镊靴,回復(fù)SYN_1和ACK_1(SYN_2 + 1)铣卡,S1的狀態(tài)由SYN_SEND--->SYN_RCVD。
    2.3 S2收到SYN_1偏竟,回復(fù)SYN_2和ACK_2(SYN_1 + 1)煮落,S2的狀態(tài)由SYN_SEND--->SYN_RCVD。
    2.4 S2收到ACK_1和SYN_1踊谋,S2的狀態(tài)由SYN_RCVD--->ESTABLISHED蝉仇。
    2.5 S1收到ACK_2和SYN_2,S1的狀態(tài)由SYN_RCVD--->ESTABLISHED殖蚕。

斷開連接

  • 正常情況
    1.1 C調(diào)用close轿衔,發(fā)送FIN_1,C的狀態(tài)由ESTABLISHED--->FIN_WAIT_1睦疫。
    1.2 S收到FIN_1害驹,發(fā)送ACK_1(FIN_1 + 1),S的狀態(tài)由ESTABLISHED--->CLOSE_WAIT蛤育。
    1.3 C收到ACK_1宛官,C的狀態(tài)由FIN_WAIT_1--->FIN_WAIT_2葫松。
    1.4 S調(diào)用close,發(fā)送FIN_2底洗,S的狀態(tài)由CLOSE_WAIT--->LAST_ACK腋么。
    1.5 C收到FIN_2, 發(fā)送ACK_2(FIN_2 + 1)亥揖,C的狀態(tài)由FIN_WAIT_2--->TIME_WAIT党晋。
    1.6 S收到ACK_2,S狀態(tài)由CLOSE_WAIT--->CLOSED徐块。
    1.7 C經(jīng)過2個MSL(Maximum Segment Lifetime),之所以要等待2個MSL灾而,是因為S在發(fā)送FIN_2后胡控,會等待1個MSL,如果1個MSL內(nèi)未收到ACK_2旁趟,則S認(rèn)為FIN_2丟包了昼激,會重發(fā)FIN_2,S重發(fā)的FIN_2到達(dá)C最大的時間為2個MSL锡搜,因此如果C在2個MSL內(nèi)未收到FIN_2橙困,則認(rèn)為S已收到ACK_2。C的狀態(tài)由TIME_WAIT--->CLOSED耕餐。
  • 特殊情況
    2.1 C調(diào)用close凡傅,發(fā)送FIN_1,C的狀態(tài)由ESTABLISHED--->FIN_WAIT_1肠缔。
    2.2 S收到FIN_1夏跷,S調(diào)用close,發(fā)送FIN_2的同時帶上ACK_1(FIN_1 + 1)明未,S的狀態(tài)由ESTABLISHED--->LAST_ACK槽华。
    2.3 C收到FIN_2和ACK_1,發(fā)送ACK_2(FIN_2 + 1)趟妥,C的狀態(tài)由FIN_WAIT_1--->TIME_WAIT猫态。
    2.4 S收到ACK_2,S狀態(tài)由CLOSE_WAIT--->CLOSED披摄。
    2.5 C經(jīng)過2MSL亲雪,C的狀態(tài)由TIME_WAIT--->CLOSED。
  • 同時關(guān)閉
    3.1 S1和S2同時調(diào)用close行疏,發(fā)送FIN(其中S1發(fā)送FIN_1匆光,S2發(fā)送FIN_2),S1和S2的狀態(tài)都由ESTABLISHED--->FIN_WAIT_1酿联。
    3.2 S1收到FIN_2终息,發(fā)送ACK_1(FIN_2 + 1)夺巩,S1的狀態(tài)由FIN_WAIT_1--->CLOSING。
    3.3 S2收到FIN_1周崭,發(fā)送ACK_2(FIN_1 + 1)柳譬,S2的狀態(tài)由FIN_WAIT_2--->CLOSING。
    3.4 S2收到ACK_1续镇,S2的狀態(tài)由CLOSING--->TIME_WAIT美澳。
    3.5 S1收到ACK_2,S1狀態(tài)由CLOSING--->TIME_WAIT摸航。
    3.6 S1和S2經(jīng)過2MSL制跟,S1和S2的狀態(tài)由TIME_WAIT--->CLOSED。

Ref:
TCP網(wǎng)絡(luò)關(guān)閉的狀態(tài)變換時序圖
TCP 的那些事兒(上)
https://nmap.org/book/tcpip-ref.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末酱虎,一起剝皮案震驚了整個濱河市雨膨,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌读串,老刑警劉巖聊记,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異恢暖,居然都是意外死亡排监,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進(jìn)店門杰捂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來舆床,“玉大人,你說我怎么就攤上這事嫁佳∏偷埽” “怎么了?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵脱拼,是天一觀的道長瞒瘸。 經(jīng)常有香客問我,道長熄浓,這世上最難降的妖魔是什么情臭? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮赌蔑,結(jié)果婚禮上俯在,老公的妹妹穿的比我還像新娘。我一直安慰自己娃惯,他們只是感情好跷乐,可當(dāng)我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著趾浅,像睡著了一般愕提。 火紅的嫁衣襯著肌膚如雪馒稍。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天浅侨,我揣著相機(jī)與錄音纽谒,去河邊找鬼。 笑死如输,一個胖子當(dāng)著我的面吹牛鼓黔,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播不见,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼澳化,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了稳吮?” 一聲冷哼從身側(cè)響起肆捕,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎盖高,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體眼虱,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡喻奥,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了捏悬。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片撞蚕。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖过牙,靈堂內(nèi)的尸體忽然破棺而出甥厦,到底是詐尸還是另有隱情,我是刑警寧澤寇钉,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布刀疙,位于F島的核電站,受9級特大地震影響扫倡,放射性物質(zhì)發(fā)生泄漏谦秧。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一撵溃、第九天 我趴在偏房一處隱蔽的房頂上張望疚鲤。 院中可真熱鬧,春花似錦缘挑、人聲如沸集歇。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽诲宇。三九已至际歼,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間焕窝,已是汗流浹背蹬挺。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留它掂,地道東北人巴帮。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像虐秋,于是被迫代替她去往敵國和親榕茧。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,033評論 2 355

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