關(guān)于 BitTorrent 的 Fast Extension 你必須要知道的

Fast Extension 協(xié)議擴(kuò)展的開啟方式系忙,需要在 BitTorrent 握手協(xié)議中設(shè)置一位特定的二進(jìn)制位來開啟叫编。在 BitTorrent 握手協(xié)議中的保留字節(jié)(reserved byte)的第三個(gè)最低有效位(third least significant bit)設(shè)置為 1裕循,即將其與 0x04 進(jìn)行按位或運(yùn)算时迫,來啟用 Fast Extension 。例如:

  reserved[7] |= 0x04

如果連接的兩端都設(shè)置了這一位惫搏,那么 Fast Extension 就會(huì)被啟用具温,并且可以使用其中的四個(gè)擴(kuò)展功能:Have None/Have All 、 Reject Requests 筐赔、 Suggestions 和 Allowed Fast铣猩。

需要注意的是,F(xiàn)ast Extension 只有在支持該協(xié)議擴(kuò)展的兩個(gè) BitTorrent 客戶端之間建立連接時(shí)才能生效茴丰。否則达皿,即使設(shè)置了這一位,也無法啟用 Fast Extension 较沪。

BitTorrent 協(xié)議中消息的語法指定所有整數(shù)都是四個(gè)字節(jié)的大端序鳞绕,并且所有消息都以一個(gè)整數(shù)的消息長(zhǎng)度開始。此外尸曼,它還指定除 Keep-Alive 外的所有消息將具有單個(gè)字節(jié)的操作碼和零個(gè)或多個(gè)依賴于操作碼的參數(shù)们何。聲明應(yīng)按照 IETF RFC 2119 中所述的方式解釋某些關(guān)鍵詞(MUST 、 MUST NOT 控轿、 REQUIRED 冤竹、 SHALL 、 SHALL NOT 茬射、 SHOULD 鹦蠕、 SHOULD NOT 、 RECOMMENDED 在抛、 MAY 和 OPTIONAL)钟病。這意味著這些單詞具有在 RFC 中定義的特定含義,它們用于指示對(duì)特定動(dòng)作或行為的要求或建議水平。例如肠阱,“MUST” 表示必須遵循某項(xiàng)要求票唆,“SHOULD” 則表示應(yīng)該遵循某項(xiàng)建議,除非存在充分理由不這樣做屹徘。

現(xiàn)有消息語義的修改

Fast Extension 對(duì)請(qǐng)求(Request)走趋、阻塞(Choke)、取消阻塞(Unchoke)和取消請(qǐng)求(Cancel)消息的語義進(jìn)行修改噪伊,并添加了一個(gè)拒絕請(qǐng)求(Reject Request)消息〔净停現(xiàn)在,每個(gè)請(qǐng)求都保證只會(huì)收到一個(gè)響應(yīng)鉴吹,即相應(yīng)的拒絕或相應(yīng)的 piece 消息姨伟。即使請(qǐng)求被取消,接收到取消請(qǐng)求的節(jié)點(diǎn)也應(yīng)該發(fā)送相應(yīng)的拒絕或相應(yīng)的 piece :正在處理中的請(qǐng)求仍然允許完成拙寡。阻塞不再隱含地拒絕所有掛起的請(qǐng)求授滓,從而消除了一些可能導(dǎo)致重復(fù)請(qǐng)求不必要的 piece 的競(jìng)爭(zhēng)條件琳水。此外肆糕,如果一個(gè)節(jié)點(diǎn)收到了一個(gè)從未請(qǐng)求的 piece ,那么它必須關(guān)閉連接在孝。

Have All/Have None

  *Have All*: <len=0x0001> <op=0x0E>
  *Have None*: <len=0x0001><op=0x0F>
  這兩種消息都包含一個(gè)長(zhǎng)度為 1 字節(jié)的整數(shù)和一個(gè)操作碼诚啃,其中 "Have All" 的操作碼是 0x0E,"Have None" 的操作碼是 0x0F 私沮。當(dāng)存在這兩個(gè)消息時(shí)始赎,它們會(huì)替換掉 “Have Bitfield” 消息。在握手之后仔燕,必須恰好出現(xiàn)一個(gè) “Have All” 造垛、"Have None" 或 "Have Bitfield" 中的一個(gè)。

“Have All” 和 “Have None” 是 BitTorrent 協(xié)議中的消息類型晰搀,表示發(fā)送方已經(jīng)擁有所有或者沒有任何 piece 五辽。當(dāng)存在這兩個(gè)消息時(shí),它們會(huì)替換掉 “Have Bitfield” 消息外恕。在握手之后杆逗,必須恰好出現(xiàn)一個(gè) “Have All” 、”Have None” 或 “Have Bitfield” 中的一個(gè)鳞疲。

這些消息的目的是為了節(jié)省帶寬罪郊,并且避免沒有 piece 時(shí)不發(fā)送任何消息的特殊情況。當(dāng) Fast Extension 被禁用時(shí)尚洽,如果某個(gè)節(jié)點(diǎn)接收到 “Have All” 或 “Have None” 消息悔橄,則該節(jié)點(diǎn)必須關(guān)閉連接。

建議性 Piece

  *Suggest Piece*: <len=0x0005><op=0x0D><index>      

“Suggest Piece“ 是一個(gè)建議性的消息,意味著” 您可能想要下載這個(gè) piece” 癣疟。它的預(yù)期用途是為了在不降低吞吐量的情況下進(jìn)行超級(jí)共享(super-seeding1)尺铣,以避免重復(fù)下載,并使磁盤 I/O 受限的種子可以上傳連續(xù)或相同的數(shù)據(jù)塊争舞,以避免過多的磁盤查找版扩。在所有情況下贡必,種子應(yīng)該操作以在網(wǎng)絡(luò)中維護(hù)大致相等數(shù)量的每個(gè)塊的副本。

對(duì)于任何給定時(shí)間,節(jié)點(diǎn)可以發(fā)送多個(gè)”Suggest Piece” 消息存皂。如果接收方收到多個(gè)”Suggest Piece” 消息,則可能會(huì)將其解釋為表示所有建議的塊都同樣適合下載添谊。

當(dāng)禁用 Fast Extension 時(shí)痪伦,如果一個(gè)節(jié)點(diǎn)收到了一個(gè)”Suggest Piece” 消息,則該節(jié)點(diǎn)必須關(guān)閉連接遭贸。

Reject Request 拒絕請(qǐng)求

  *Reject Request*: <len=0x000D><op=0x10><index><begin><length>
  通過發(fā)送這個(gè)消息戈咳,Peer 可以告訴其他 Peer 自己無法提供所請(qǐng)求的數(shù)據(jù)塊。接收方在收到該消息后壕吹,會(huì)將相應(yīng)的請(qǐng)求從隊(duì)列中刪除著蛙,并嘗試向其他 Peer 請(qǐng)求相同的數(shù)據(jù)塊。

Reject Request 用于通知請(qǐng)求方耳贬,它所請(qǐng)求的數(shù)據(jù)塊無法被滿足踏堡。

如果 Fast Extension 沒有啟用,且一個(gè)節(jié)點(diǎn)接收到了 Reject Request 消息咒劲,則該節(jié)點(diǎn)必須關(guān)閉與請(qǐng)求方之間的連接顷蟆。

啟用 Fast Extension 時(shí),節(jié)點(diǎn)在處理 Reject Request 消息時(shí)的規(guī)范行為:

  • 如果一個(gè)節(jié)點(diǎn)接收到一個(gè)未曾發(fā)送請(qǐng)求的 Reject Request 消息腐魂,則它應(yīng)該關(guān)閉與發(fā)出該消息的節(jié)點(diǎn)之間的連接帐偎。
  • 當(dāng)一個(gè)節(jié)點(diǎn)向另一個(gè)節(jié)點(diǎn)發(fā)送 Choke 消息時(shí),它必須拒絕該節(jié)點(diǎn)發(fā)出的所有請(qǐng)求蛔屹,除非這些請(qǐng)求涉及允許的快速集合中的數(shù)據(jù)塊削樊。節(jié)點(diǎn)應(yīng)該先 choke 再拒絕請(qǐng)求,這樣收到 Choke 消息的節(jié)點(diǎn)不會(huì)重新請(qǐng)求那些被 choke 的數(shù)據(jù)塊判导。
  • 如果一個(gè)節(jié)點(diǎn)收到了來自被 choke 的節(jié)點(diǎn)的請(qǐng)求嫉父,則它會(huì)拒絕該請(qǐng)求,除非所請(qǐng)求的數(shù)據(jù)塊在允許的快速集合中眼刃。
  • 如果一個(gè)節(jié)點(diǎn)收到了太多來自被 choke 的節(jié)點(diǎn)的請(qǐng)求绕辖,則它可以選擇關(guān)閉連接而不是拒絕這些請(qǐng)求。但是擂红,要考慮到一旦一個(gè)節(jié)點(diǎn)被 choke仪际,緩沖區(qū)可以需要幾秒鐘才能排空并且消息傳播才能完成围小。因此,需要在決定關(guān)閉連接之前仔細(xì)考慮這個(gè)問題树碱。

Allowed Fast

  *Allowed Fast*: <len=0x0005><op=0x11><index>

使用指定的 BitTorrent 協(xié)議肯适,新加入的節(jié)點(diǎn)由于缺少數(shù)據(jù)片段,需要等待一段時(shí)間才能與其他節(jié)點(diǎn)進(jìn)行有效的文件共享成榜。在這個(gè)過程中框舔,節(jié)點(diǎn)可能會(huì)不斷地被 choke(阻止上傳),導(dǎo)致共享效率降低赎婚。

為了解決這個(gè)問題刘绣,BitTorrent 協(xié)議中引入了 “Allowed Fast” 消息。這個(gè)消息告訴其他節(jié)點(diǎn)挣输,即使自己處于 choke 狀態(tài)纬凤,也可以向它請(qǐng)求某些數(shù)據(jù)片段,并保證會(huì)立即響應(yīng)撩嚼。這樣停士,其他節(jié)點(diǎn)就可以更快地獲取到需要的數(shù)據(jù),而新加入節(jié)點(diǎn)也可以更快地開始參與 tit-for-tat 的交換過程完丽,從而提高整個(gè)網(wǎng)絡(luò)的文件共享效率恋技。

在這個(gè)協(xié)議中,當(dāng)一個(gè)節(jié)點(diǎn)擁有某個(gè)文件的一部分時(shí)舰涌,它可以把這些 piece 分享給其他節(jié)點(diǎn)猖任。當(dāng)其他節(jié)點(diǎn)需要下載這個(gè)文件時(shí),它們可以從那個(gè)節(jié)點(diǎn)處請(qǐng)求這些 piece瓷耙,以便更快地完成文件的下載。

而 “Allowed Fast 集合” 則是指每個(gè)節(jié)點(diǎn)所允許請(qǐng)求的一組 piece 的集合刁赖。為了保證所有節(jié)點(diǎn)之間的數(shù)據(jù)請(qǐng)求都是公平的搁痛,在協(xié)議中使用了一個(gè)經(jīng)過驗(yàn)證的生成算法來生成這個(gè)集合。這個(gè)算法會(huì)為每個(gè)接收消息的節(jié)點(diǎn)生成唯一的 piece 索引宇弛,使得當(dāng)兩個(gè)節(jié)點(diǎn)都提供了 k 個(gè) piece 時(shí)鸡典,它們所能夠請(qǐng)求的 piece 的數(shù)量也是相同的;如果其中一個(gè)節(jié)點(diǎn)提供了 k+1 個(gè) piece枪芒,則請(qǐng)求數(shù)量也會(huì)相應(yīng)增加一個(gè)彻况。 k 的值應(yīng)該足夠小以避免濫用,但又足夠大以實(shí)現(xiàn) “以牙還牙” 的策略舅踪。作者目前將 k 的默認(rèn)值設(shè)置為 10纽甘,但節(jié)點(diǎn)可以自由更改這個(gè)數(shù)字,以適應(yīng)不同的負(fù)載情況抽碌。

發(fā)送方可以在 Allowed Fast 消息中列出它還沒有實(shí)際擁有的 pieces 悍赢,接收方不能根據(jù) Allowed Fast 消息認(rèn)為發(fā)送方確實(shí)擁有這些 pieces 。這樣做的目的是為了允許節(jié)點(diǎn)在連接開始時(shí)生成和通信允許快速集合。然而左权,發(fā)送方隨時(shí)都可以發(fā)送 Allowed Fast 消息皮胡。

一個(gè)節(jié)點(diǎn)如果有足夠的資源,應(yīng)該向任何一個(gè)起始節(jié)點(diǎn)發(fā)送 Allowed Fast 消息赏迟,以提高其他節(jié)點(diǎn)下載文件分塊的速度屡贺。但是,在某些情況下锌杀,節(jié)點(diǎn)可以拒絕已經(jīng)發(fā)送了 Allowed Fast pieces 的請(qǐng)求烹笔,例如本地節(jié)點(diǎn)資源不足、請(qǐng)求的 pieces 已經(jīng)發(fā)送給請(qǐng)求的節(jié)點(diǎn)抛丽、或者請(qǐng)求節(jié)點(diǎn)并非一個(gè)起始節(jié)點(diǎn)谤职。此外,當(dāng)前實(shí)現(xiàn)的規(guī)則還規(guī)定了一種情況亿鲜,即當(dāng)請(qǐng)求節(jié)點(diǎn)已經(jīng)下載了超過 k 個(gè) pieces 時(shí)允蜈,請(qǐng)求被拒絕。

當(dāng) Fast 擴(kuò)展被禁用時(shí)蒿柳,只要節(jié)點(diǎn)收到了 Allowed Fast 消息饶套,它就沒有能力處理這種消息,因此必須斷開與發(fā)送方的連接垒探。這個(gè)規(guī)則的目的是確保協(xié)議的兼容性和正確性妓蛮,保證所有節(jié)點(diǎn)都能夠按照相同的規(guī)則進(jìn)行通信,從而實(shí)現(xiàn)文件分塊的有效下載和傳輸圾叼。

Allowed Fast Set 機(jī)制

計(jì)算對(duì)等節(jié)點(diǎn)的快速列表的標(biāo)準(zhǔn)算法中所有的整數(shù)都是四個(gè)字節(jié)(32 位)的網(wǎng)絡(luò)字節(jié)序(大端序)蛤克。 [a:b] 表示從 a 到 b 的連續(xù)字節(jié)序列,不包括 b夷蚊,即 (a, a+1, a+2,…, b-1) 构挤。 x[a:b] 表示數(shù)組 x 中從索引 a 開始到索引 b(但不包括 b)的子序列。

計(jì)算網(wǎng)絡(luò)地址的方法惕鼓。其中筋现,“ip” 代表 P’*s IPv4 地址。該方法目前不支持 IPv6 地址箱歧。如果對(duì)等方在 NAT 后面矾飞,則 “ip” 應(yīng)為 NAT 的外部 IP 地址。由于發(fā)送 “Allowed Fast” 消息的節(jié)點(diǎn)計(jì)算集合呀邢,因此通常正確的 “ip” 是連接另一端的 “ip” 地址洒沦。計(jì)算集合的主機(jī)可以根據(jù)需要使用連接另一端的 “ip” 地址。簡(jiǎn)而言之驼鹅,這意味著微谓,在計(jì)算集合時(shí)森篷,可以選擇使用連接另一端的 IP 地址作為計(jì)算中的 IP 地址,而不一定是自己的 IP 地址豺型。

用 “sz” 代表種子文件中分片的數(shù)量仲智。而 “a” 代表允許快速下載的集合,該集合包含一些不在正常下載順序中的分片姻氨。最后钓辆,“k” 代表被允許以快速方式下載的分片數(shù)量,即允許快速下載的集合中所包含的分片數(shù)目肴焊。

  x = 0xFFFFFF00 & ip                           (1)
  x.append(infohash)                            (2)
  while |a| < k:
    x = SHA1(x)                                 (3)
    for i in [0:5] and |a| < k:                 (4)
      j = i*4                                   (5)
      y = x[j:j+4]                              (6)
      index = y % sz                            (7)
      if index not in a:                        (8)
        add index to a                          (9)

第一步(1)選擇節(jié)點(diǎn) P’*s 的 IP 地址中最重要的八位字節(jié)前联。這樣可以防止同一個(gè)網(wǎng)絡(luò)上的用戶獲得多個(gè) Allowed Fast Set 。使用三個(gè)字節(jié)是基于經(jīng)驗(yàn)和歷史原因的娶眷。

第三步(3)在每個(gè)調(diào)用上生成一個(gè) 20 字節(jié)的隨機(jī)數(shù)似嗤。通過對(duì)前一次迭代的哈希執(zhí)行 SHA-1 哈希,我們可以生成任意長(zhǎng)度的偽隨機(jī)序列届宠。

步驟(4)到(9)將 20 字節(jié)哈希劃分為若干片段索引烁落,并將其添加到允許快速集合中。簡(jiǎn)單來說豌注,該過程將隨機(jī)數(shù)分成了 5 個(gè) 4 字節(jié)的片段伤塌,并將每個(gè)片段作為指向表示內(nèi)容不同部分的索引集合中的一個(gè)索引。如果該索引尚未被添加到允許快速集合中轧铁,則將其添加到集合中每聪。這確保只有擁有特定索引的一部分節(jié)點(diǎn)才能被選入 “允許快速” 節(jié)點(diǎn)集合。

Example Implementation 示例實(shí)現(xiàn)

以下的 C++ 實(shí)現(xiàn)由 CacheLogic 提供

void generate_fast_set(
  uint32 k,     // number of pieces in set
  uint32 sz,    // number of pieces in torrent
  const char infohash[20], // infohash of torrent
  uint32 ip, // in host byte order, ie localhost is 0x7f000001
  std::
vector<uint32> &a) // generated set of piece indices
{
   a.clear();
   std::string x;
   char buf[4];
   *(uint32*)buf = htonl(ip & 0xffffff00);
   x.assign(buf, 4);
   x.append(infohash, 20); // (3)
   while (a.size()<k) {
     x = SHA1(x); // (4)
     for ( int i=0&nbsp;; i<5 && a.size()<k; i++ ) { // (5)
       int j = i*4; // (6)
       uint32 y = ntohl(*(uint32*)(x.data()+j)); // (7)
       uint32 index = y % sz; // (8)
       if (std::find(a.begin(), a.end(), index)==a.end()) { // (9)
         a.push_back(index); // (10)
       }
     }
   }
}

此函數(shù)生成的示例結(jié)果:

7 piece allowed fast set for torrent with 1313 pieces and hex infohash
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa for node with IP 80.4.4.200:
  1059,431,808,1217,287,376,1188
9 piece allowed fast set for torrent with 1313 pieces and hex infohash
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa for node with IP 80.4.4.200:
  1059,431,808,1217,287,376,1188,353,508

總結(jié)

BitTorrent 的 Fast Extension(簡(jiǎn)稱 FAST)是一種加速下載的協(xié)議擴(kuò)展齿风,它能夠顯著提高文件下載速度药薯。 FAST 利用了一些技術(shù)手段來優(yōu)化下載過程,如多線程下載聂宾、數(shù)據(jù)塊預(yù)取和請(qǐng)求重排等果善。

具體地說,F(xiàn)AST 通過請(qǐng)求多個(gè)數(shù)據(jù)塊系谐,并在這些數(shù)據(jù)塊到達(dá)之前對(duì)它們進(jìn)行排序以減少延遲,從而使下載更快讨跟。此外纪他,F(xiàn)AST 還利用多線程下載技術(shù),同時(shí)從不同的上傳者處獲取數(shù)據(jù)塊晾匠,進(jìn)一步提高下載速度茶袒。

需要注意的是,F(xiàn)AST 只適用于支持該協(xié)議擴(kuò)展的 BitTorrent 客戶端之間的通信凉馆,因此如果你使用的客戶端不支持 FAST薪寓,那么即使有其他客戶端支持該協(xié)議擴(kuò)展亡资,也無法加速你的下載。

參考鏈接

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末向叉,一起剝皮案震驚了整個(gè)濱河市锥腻,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌母谎,老刑警劉巖瘦黑,帶你破解...
    沈念sama閱讀 219,366評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異奇唤,居然都是意外死亡幸斥,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門咬扇,熙熙樓的掌柜王于貴愁眉苦臉地迎上來甲葬,“玉大人,你說我怎么就攤上這事懈贺【眩” “怎么了?”我有些...
    開封第一講書人閱讀 165,689評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵隅居,是天一觀的道長(zhǎng)钠至。 經(jīng)常有香客問我,道長(zhǎng)胎源,這世上最難降的妖魔是什么棉钧? 我笑而不...
    開封第一講書人閱讀 58,925評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮涕蚤,結(jié)果婚禮上宪卿,老公的妹妹穿的比我還像新娘。我一直安慰自己万栅,他們只是感情好佑钾,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,942評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著烦粒,像睡著了一般休溶。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上扰她,一...
    開封第一講書人閱讀 51,727評(píng)論 1 305
  • 那天兽掰,我揣著相機(jī)與錄音,去河邊找鬼徒役。 笑死孽尽,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的忧勿。 我是一名探鬼主播杉女,決...
    沈念sama閱讀 40,447評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼瞻讽,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了熏挎?” 一聲冷哼從身側(cè)響起速勇,我...
    開封第一講書人閱讀 39,349評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎婆瓜,沒想到半個(gè)月后快集,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,820評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡廉白,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,990評(píng)論 3 337
  • 正文 我和宋清朗相戀三年个初,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片猴蹂。...
    茶點(diǎn)故事閱讀 40,127評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡院溺,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出磅轻,到底是詐尸還是另有隱情珍逸,我是刑警寧澤,帶...
    沈念sama閱讀 35,812評(píng)論 5 346
  • 正文 年R本政府宣布聋溜,位于F島的核電站谆膳,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏撮躁。R本人自食惡果不足惜漱病,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,471評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望把曼。 院中可真熱鬧杨帽,春花似錦、人聲如沸嗤军。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,017評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽叙赚。三九已至老客,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間震叮,已是汗流浹背沿量。 一陣腳步聲響...
    開封第一講書人閱讀 33,142評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留冤荆,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,388評(píng)論 3 373
  • 正文 我出身青樓权纤,卻偏偏與公主長(zhǎng)得像钓简,于是被迫代替她去往敵國(guó)和親乌妒。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,066評(píng)論 2 355

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