websocket

1 述

  • WebSocket是一種網(wǎng)絡通信協(xié)議
  • WebSocket 協(xié)議在2008年誕生谚中,2011年成為國際標準。
  • HTML5開始提供的一種瀏覽器與服務器進行全雙工通訊的網(wǎng)絡技術墓陈,屬于應用層協(xié)議。它基于TCP傳輸協(xié)議贡必,并復用HTTP的握手通道兔港,可以傳輸基于消息的文本和二進制數(shù)據(jù)。
  • 兩端都可以隨時向另一端發(fā)送數(shù)據(jù)仔拟。
  • 任何事物都不是完美的衫樊,設計限制和性能權衡始終會有,利用WebSocket 也不例外科侈,在提供自定義數(shù)據(jù)交換協(xié)議同時载佳,也不再享有在一些本由瀏覽器提供的服務和優(yōu)化臀栈,如狀態(tài)管理、壓縮权薯、緩存等。

2websocket對比http

2.1 雙向通信

Http 有 Keep-Alive

  • HTTP1.1 默認使用持久連接(persistent connection)崭闲,在一個 TCP 連接上也可以傳輸多個 Request/Response 消息對,但是 HTTP 的基本模型還是一個 Request 對應一個 Response刁俭。
  • 在雙向通信(客戶端要向服務器傳送數(shù)據(jù)韧涨,同時服務器也需要實時的向客戶端傳送信息,一個聊天系統(tǒng)就是典型的雙向通信)時一般會使用這樣幾種解決方案:
  • 1.輪詢(polling)虑粥,輪詢就會造成對網(wǎng)絡和通信雙方的資源的浪費,且非實時娩贷。
  • 2.長輪詢,?長輪詢主要是發(fā)出一個HTTP請求到服務器彬祖,然后保持連接打開以允許服務器在稍后的時間響應(由服務器確定)。
  • 3.長連接HTTP 的長連接甜熔,本質(zhì)上還是 Request/Response 消息對,仍然會造成資源的浪費腔稀、實時性不強等問題

2.2相同點

  • 都是基于 TCP 的應用層協(xié)議
  • 都使用 Request/Response 模型進行連接的建立
  • 在連接的建立過程中對錯誤的處理方式相同羽历,在這個階段 WS 可能返回和 HTTP 相同的返回碼
  • 都可以在網(wǎng)絡中傳輸數(shù)據(jù)

2.3 不同點

  • WS 使用 HTTP 來建立連接焊虏,但是定義了一系列新的 header 域秕磷,這些域在 HTTP 中并不會使用
  • WS 的連接不能通過中間人來轉發(fā),它必須是一個直接連接
  • WS 連接建立之后跳夭,通信雙方都可以在任何時刻向另一方發(fā)送數(shù)據(jù)
  • WS 連接建立之后涂圆,數(shù)據(jù)的傳輸使用幀來傳遞,不再需要 Request 消息
  • WS 的數(shù)據(jù)幀有序

2 Socket 與 WebSocket 的關系

Socket 其實并不是一個協(xié)議模狭,它工作在 OSI 模型會話層(第5層),是為了方便大家直接使用更底層協(xié)議(一般是 TCP或 UDP)而存在的一個抽象層嚼鹉。

2 和 TCP 以及 HTTP 之間的關系

WebSocket 是一個獨立的基于 TCP 的協(xié)議驱富,它與 HTTP 之間的唯一關系就是它的握手請求可以作為一個升級請求(Upgrade request)經(jīng)由 HTTP 服務器解釋(也就是可以使用 Nginx 反向代理一個 WebSocket)。

默認情況下褐鸥,WebSocket 協(xié)議使用 80 端口作為一般請求的端口,端口 443 作為基于傳輸加密層連(TLS)RFC2818 接的端口

3 優(yōu)點

說到優(yōu)點叫榕,這里的對比參照物是HTTP協(xié)議,概括地說就是:支持雙向通信晰绎,更靈活,更高效伶选,可擴展性更好。
具體優(yōu)化如下:

  • 1)支持雙向通信仰税,實時性更強会宪;
  • 2)更好的二進制支持肖卧;
  • 3)較少的控制開銷:
  • 連接創(chuàng)建后掸鹅,ws客戶端、服務端進行數(shù)據(jù)交換時巍沙,協(xié)議控制的數(shù)據(jù)包頭部較小葵姥。在不包含頭部的情況下句携,服務端到客戶端的包頭只有2~10字節(jié)(取決于數(shù)據(jù)包長度),客戶端到服務端的的話,需要加上額外的4字節(jié)的掩碼牍疏。而HTTP協(xié)議每次通信都需要攜帶完整的頭部拨齐;
  • 4)支持擴展:
  • ws協(xié)議定義了擴展鳞陨,用戶可以擴展協(xié)議瞻惋,或者實現(xiàn)自定義的子協(xié)議(比如支持自定義壓縮算法等)。
    子協(xié)議
    在使用 WebSocket 協(xié)議連接到一個 WebSocket 服務器時歼狼,客戶端可以指定其 Sec-WebSocket-Protocol 為其所期望采用的子協(xié)議集合,而服務端則可以在此集合中選取一個并返回給客戶端趟咆。
    作為服務端梅屉,必須確保選的是客戶端握手請求中的幾個子協(xié)議中的一個:
Sec-WebSocket-Protocol: chat

4 建立連接

  • WebSocket復用了HTTP的握手通道忍啸。具體指的是履植,客戶端通過HTTP請求與WebSocket服務端協(xié)商升級協(xié)議悄晃。協(xié)議升級完成后,后續(xù)的數(shù)據(jù)交換則遵照WebSocket的協(xié)議妈橄。

4.1 客戶端:申請協(xié)議升級

首先,客戶端發(fā)起協(xié)議升級請求眷蚓。可以看到叉钥,采用的是標準的HTTP報文格式篙贸,且只支持GET方法:


16251781c04e73d0.png
GET / HTTP/1.1

Host: localhost:8080

Origin: [url=http://127.0.0.1:3000]http://127.0.0.1:3000[/url]

Connection: Upgrade

Upgrade: websocket

Sec-WebSocket-Version: 13

Sec-WebSocket-Key: w4v7O6xFTi36lq3RNcgctw==

重點請求首部意義如下:

Connection: Upgrade:表示要升級協(xié)議

Upgrade: websocket:表示要升級到websocket協(xié)議。

Sec-WebSocket-Version: 13:表示websocket的版本爵川。如果服務端不支持該版本,需要返回一個Sec-WebSocket-Versionheader,里面包含服務端支持的版本號值依。

Sec-WebSocket-Key:與后面服務端響應首部的Sec-WebSocket-Accept是配套的碟案,提供基本的防護愿险,比如惡意的連接蟆淀,或者無意的連接。

注意:上面請求省略了部分非重點請求首部熔任。由于是標準的HTTP請求,類似Host甫匹、Origin、Cookie等請求首部會照常發(fā)送兵迅。在握手階段薪贫,可以通過相關請求首部進行 安全限制恍箭、權限校驗等瞧省。

4.2 服務端:響應協(xié)議升級

任何其他的非 101 表示 WebSocket 握手還沒有結束,客戶端需要使用原有的 HTTP 的方式去響應那些狀態(tài)碼鞍匾。
服務端返回內(nèi)容如下,狀態(tài)代碼101表示協(xié)議切換:

HTTP/1.1 101 Switching Protocols

Connection:Upgrade

Upgrade: websocket

Sec-WebSocket-Accept: Oy4NRAQ13jhfONC7bP8dTKb4PTU=

到此完成協(xié)議升級构拳,后續(xù)的數(shù)據(jù)交互都按照新的協(xié)議來梁棠。
備注:每個header都以\r\n結尾置森,并且最后一行加上一個額外的空行\(zhòng)r\n掰茶。此外,服務端回應的HTTP狀態(tài)碼只能在握手階段使用盐碱。過了握手階段后把兔,就只能采用特定的錯誤碼瓮顽。

4.3 Sec-WebSocket-Accept的計算

  • Sec-WebSocket-Accept根據(jù)客戶端請求首部的Sec-WebSocket-Key計算出來。
    計算公式為:
  • 1)將Sec-WebSocket-Key跟258EAFA5-E914-47DA-95CA-C5AB0DC85B11拼接缕贡;
  • 2)通過SHA1計算出摘要,并轉成base64字符串晾咪。

4.4 關閉握手

  • 任意一端都可以選擇關閉握手過程。
    需要關閉握手的一方通過發(fā)送一個特定的控制序列去開始一個關閉握手的過程谍倦。
  • 一端一旦接受到了來自另一端的請求關閉控制幀后泪勒,接收到關閉請求的一端如果還沒有返回一個作為響應的關閉幀的話,那么它需要先發(fā)送一個關閉幀圆存。
  • 在接受到了對方響應的關閉幀之后,發(fā)起關閉請求的那一端就可以關閉連接了沦辙。
  • 在發(fā)送了請求關閉控制序列之后,發(fā)送請求的一端將不可以再發(fā)送其他的數(shù)據(jù)內(nèi)容油讯;
  • 同樣的,一但接收到了一端的請求關閉控制序列之后,來自那一端的其他數(shù)據(jù)內(nèi)容將被忽略衫冻。
  • 注意這里的說的是數(shù)據(jù)內(nèi)容,控制幀還是可以響應的隅俘。
  • 兩邊同時發(fā)起關閉請求也是可以的。

作者:mconintet
鏈接:http://www.reibang.com/p/867274a5e054
來源:簡書
著作權歸作者所有碌宴。商業(yè)轉載請聯(lián)系作者獲得授權,非商業(yè)轉載請注明出處贰镣。

5 數(shù)據(jù)幀格式

  • 客戶端、服務端數(shù)據(jù)的交換碑隆,離不開數(shù)據(jù)幀格式的定義。因此上煤,在實際講解數(shù)據(jù)交換之前,我們先來看下WebSocket的數(shù)據(jù)幀格式拴疤。
  • WebSocket客戶端独泞、服務端通信的最小單位是幀(frame)呐矾,由1個或多個幀組成一條完整的消息(message)阐肤。
    詳情如下:
  • 發(fā)送端:將消息切割成多個幀,并發(fā)送給服務端孕惜;
  • 接收端:接收消息幀,并將關聯(lián)的幀重新組裝成完整的消息毫炉。

5.1 數(shù)據(jù)幀格式概覽

  • 從左到右削罩,單位是比特瞄勾。比如FIN弥激、RSV1各占據(jù)1比特,opcode占據(jù)4比特微服;
  • 內(nèi)容包括了標識、操作代碼糙麦、掩碼、數(shù)據(jù)赡磅、數(shù)據(jù)長度等宝与。
1500839-28ffabe01fda8bdd.jpg

5.2 數(shù)據(jù)幀格式詳解

  • FIN:1個比特
    如果是1冶匹,表示這是消息(message)的最后一個分片(fragment),如果是0徙硅,表示不是是消息(message)的最后一個分片(fragment)搞疗。
  • RSV1, RSV2, RSV3:各占1個比特

一般情況下全為0。當客戶端匿乃、服務端協(xié)商采用WebSocket擴展時,這三個標志位可以非0幢炸,且值的含義由擴展進行定義。如果出現(xiàn)非零的值佛嬉,且并沒有采用WebSocket擴展,連接出錯暖呕。

  • Opcode: 4個比特
  • 操作代碼苞氮,Opcode的值決定了應該如何解析后續(xù)的數(shù)據(jù)載荷(data payload)湾揽。如果操作代碼是不認識的笼吟,那么接收端應該斷開連接(fail the connection)〈铮可選的操作代碼如下:
  • %x0:表示一個延續(xù)幀。當Opcode為0時毫目,表示本次數(shù)據(jù)傳輸采用了數(shù)據(jù)分片诲侮,當前收到的數(shù)據(jù)幀為其中一個數(shù)據(jù)分片箱蟆;
  • %x1:表示這是一個文本幀(frame)沟绪;
  • %x2:表示這是一個二進制幀(frame)空猜;
  • %x3-7:保留的操作代碼恨旱,用于后續(xù)定義的非控制幀坝疼;
  • %x8:表示連接斷開;
  • %x8:表示這是一個ping操作钝凶;
  • %xA:表示這是一個pong操作;
  • %xB-F:保留的操作代碼耕陷,用于后續(xù)定義的控制幀。
  • Mask: 1個比特
  • 表示是否要對數(shù)據(jù)載荷進行掩碼操作饺蔑。從客戶端向服務端發(fā)送數(shù)據(jù)時,需要對數(shù)據(jù)進行掩碼操作猾警;從服務端向客戶端發(fā)送數(shù)據(jù)時隆敢,不需要對數(shù)據(jù)進行掩碼操作。
  • 如果服務端接收到的數(shù)據(jù)沒有進行過掩碼操作筑公,服務端需要斷開連接。
  • 如果Mask是1匣屡,那么在Masking-key中會定義一個掩碼鍵(masking key),并用這個掩碼鍵來對數(shù)據(jù)載荷進行反掩碼誉结。所有客戶端發(fā)送到服務端的數(shù)據(jù)幀,Mask都是1惩坑。
  • Payload length:數(shù)據(jù)載荷的長度也拜,單位是字節(jié)。為7位慢哈,或7+16位,或1+64位
  • 假設數(shù)Payload length === x卵贱,如果:
  • x為0~126:數(shù)據(jù)的長度為x字節(jié)侣集;
  • x為126:后續(xù)2個字節(jié)代表一個16位的無符號整數(shù)兰绣,該無符號整數(shù)的值為數(shù)據(jù)的長度;
  • x為127:后續(xù)8個字節(jié)代表一個64位的無符號整數(shù)(最高位為0)缀辩,該無符號整數(shù)的值為數(shù)據(jù)的長度。
    此外斋泄,如果payload length占用了多個字節(jié)的話,payload length的二進制表達采用網(wǎng)絡序(big endian炫掐,重要的位在前)
  • Masking-key:0或4字節(jié)(32位)
  • 所有從客戶端傳送到服務端的數(shù)據(jù)幀睬涧,數(shù)據(jù)載荷都進行了掩碼操作,Mask為1畦浓,且攜帶了4字節(jié)的Masking-key。如果Mask為0讶请,則沒有Masking-key。
  • 備注:載荷數(shù)據(jù)的長度论巍,不包括mask key的長度风响。
  • Payload data:(x+y) 字節(jié)
  • 載荷數(shù)據(jù):
  • 包括了擴展數(shù)據(jù)嘉汰、應用數(shù)據(jù)状勤。其中,擴展數(shù)據(jù)x字節(jié)密似,應用數(shù)據(jù)y字節(jié);
  • 擴展數(shù)據(jù):
  • 如果沒有協(xié)商使用擴展的話残腌,擴展數(shù)據(jù)數(shù)據(jù)為0字節(jié)。所有的擴展都必須聲明擴展數(shù)據(jù)的長度废累,或者可以如何計算出擴展數(shù)據(jù)的長度脱盲。此外,擴展如何使用必須在握手階段就協(xié)商好钱反。如果擴展數(shù)據(jù)存在,那么載荷數(shù)據(jù)長度必須將擴展數(shù)據(jù)的長度包含在內(nèi)哎壳;
  • 應用數(shù)據(jù):
  • 任意的應用數(shù)據(jù)尚卫,在擴展數(shù)據(jù)之后(如果存在擴展數(shù)據(jù))归榕,占據(jù)了數(shù)據(jù)幀剩余的位置吱涉。載荷數(shù)據(jù)長度 減去 擴展數(shù)據(jù)長度,就得到應用數(shù)據(jù)的長度怎爵。

5.3 掩碼算法

  • 掩碼鍵(Masking-key)是由客戶端挑選出來的32位的隨機數(shù)特石。掩碼操作不會影響數(shù)據(jù)載荷的長度鳖链。
    掩碼、反掩碼操作都采用如下算法逞敷。
首先著恩,假設:
original-octet-i:為原始數(shù)據(jù)的第i字節(jié)。
transformed-octet-i:為轉換后的數(shù)據(jù)的第i字節(jié)顶瞳。
j:為i mod 4的結果。
masking-key-octet-j:為mask key第j字節(jié)慨菱。
算法描述為: 
original-octet-i 與 masking-key-octet-j 異或后,得到 transformed-octet-i符喝。
即:j = i MOD 4
transformed-octet-i = original-octet-i XOR masking-key-octet-j

6 數(shù)據(jù)傳遞

  • 一旦WebSocket客戶端、服務端建立連接后畏腕,后續(xù)的操作都是基于數(shù)據(jù)幀的傳遞。WebSocket根據(jù)opcode來區(qū)分操作的類型描馅。比如0x8表示斷開連接,0x0-0x2表示數(shù)據(jù)交互铭污。

6.1 數(shù)據(jù)分片

  • WebSocket的每條消息可能被切分成多個數(shù)據(jù)幀。當WebSocket的接收方收到一個數(shù)據(jù)幀時岂膳,會根據(jù)FIN的值來判斷磅网,是否已經(jīng)收到消息的最后一個數(shù)據(jù)幀。
  • FIN=1表示當前數(shù)據(jù)幀為消息的最后一個數(shù)據(jù)幀知市,此時接收方已經(jīng)收到完整的消息,可以對消息進行處理嫂丙。FIN=0,則接收方還需要繼續(xù)監(jiān)聽接收其余的數(shù)據(jù)幀诽表。
  • 此外,opcode在數(shù)據(jù)交換的場景下竿奏,表示的是數(shù)據(jù)的類型腥放。0x01表示文本,0x02表示二進制秃症。而0x00比較特殊,表示延續(xù)幀(continuation frame)种柑,顧名思義,就是完整消息對應的數(shù)據(jù)幀還沒接收完荠雕。

6.2 數(shù)據(jù)分片例子

客戶端向服務端兩次發(fā)送消息,服務端收到消息后回應客戶端炸卑,這里主要看客戶端往服務端發(fā)送的消息。

第一條消息:

FIN=1, 表示是當前消息的最后一個數(shù)據(jù)幀盖文。服務端收到當前數(shù)據(jù)幀后,可以處理消息。opcode=0x1蒋失,表示客戶端發(fā)送的是文本類型。

第二條消息:

1)FIN=0篙挽,opcode=0x1,表示發(fā)送的是文本類型链韭,且消息還沒發(fā)送完成煮落,還有后續(xù)的數(shù)據(jù)幀敞峭;

2)FIN=0蝉仇,opcode=0x0,表示消息還沒發(fā)送完成沉迹,還有后續(xù)的數(shù)據(jù)幀,當前的數(shù)據(jù)幀需要接在上一條數(shù)據(jù)幀之后鞭呕;

3)FIN=1宛官,opcode=0x0,表示消息已經(jīng)發(fā)送完成摘刑,沒有后續(xù)的數(shù)據(jù)幀,當前的數(shù)據(jù)幀需要接在上一條數(shù)據(jù)幀之后枷恕。服務端可以將關聯(lián)的數(shù)據(jù)幀組裝成完整的消息。

Client: FIN=1, opcode=0x1, msg="hello"

Server: (process complete message immediately) Hi.

Client: FIN=0, opcode=0x1, msg="and a"

Server: (listening, new message containing text started)

Client: FIN=0, opcode=0x0, msg="happy new"

Server: (listening, payload concatenated to previous message)

Client: FIN=1, opcode=0x0, msg="year!"

Server: (process complete message) Happy new year to you too!

7 連接保持+心跳

  • WebSocket為了保持客戶端未玻、服務端的實時雙向通信,需要確卑饨耍客戶端、服務端之間的TCP通道保持連接沒有斷開锡搜。然而瞧掺,對于長時間沒有數(shù)據(jù)往來的連接耕餐,如果依舊長時間保持著辟狈,可能會浪費包括的連接資源。
  • 但不排除有些場景明未,客戶端壹蔓、服務端雖然長時間沒有數(shù)據(jù)往來,但仍需要保持連接佣蓉。
  • 這個時候,可以采用心跳來實現(xiàn):
  • 發(fā)送方->接收方:ping
  • 接收方->發(fā)送方:pong
  • ping偏螺、pong的操作,對應的是WebSocket的兩個控制幀酿联,opcode分別是0x9夺巩、0xA。

8 Sec-WebSocket-Key/Accept的作用

Sec-WebSocket-Key/Sec-WebSocket-Accept在主要作用在于提供基礎的防護柳譬,減少惡意連接、意外連接美澳。

  • 作用大致歸納如下:
  • 1)避免服務端收到非法的websocket連接(比如http客戶端不小心請求連接websocket服務摸航,此時服務端可以直接拒絕連接)舅桩;
  • 2)確保服務端理解websocket連接。因為ws握手階段采用的是http協(xié)議擂涛,因此可能ws連接是被一個http服務器處理并返回的,此時客戶端可以通過Sec-WebSocket-Key來確保服務端認識ws協(xié)議恢暖。(并非百分百保險狰右,比如總是存在那么些無聊的http服務器,光處理Sec-WebSocket-Key挟阻,但并沒有實現(xiàn)ws協(xié)議峭弟。。瞒瘸。);
  • 3)用瀏覽器里發(fā)起ajax請求省撑,設置header時俯在,Sec-WebSocket-Key以及其他相關的header是被禁止的。這樣可以避免客戶端發(fā)送ajax請求時跷乐,意外請求協(xié)議升級(websocket upgrade);
  • 4)可以防止反向代理(不理解ws協(xié)議)返回錯誤的數(shù)據(jù)愕提。比如反向代理前后收到兩次ws連接的升級請求馒稍,反向代理把第一次請求的返回給cache住,然后第二次請求到來時直接把cache住的請求給返回(無意義的返回)浅侨;
  • 5)Sec-WebSocket-Key主要目的并不是確保數(shù)據(jù)的安全性纽谒,因為Sec-WebSocket-Key、Sec-WebSocket-Accept的轉換計算公式是公開的如输,而且非常簡單鼓黔,最主要的作用是預防一些常見的意外情況(非故意的)央勒。
    強調(diào):Sec-WebSocket-Key/Sec-WebSocket-Accept 的換算,只能帶來基本的保障请祖,但連接是否安全订歪、數(shù)據(jù)是否安全、客戶端/服務端是否合法的 ws客戶端肆捕、ws服務端刷晋,其實并沒有實際性的保證。

9 數(shù)據(jù)掩碼的作用

  • WebSocket協(xié)議中慎陵,數(shù)據(jù)掩碼的作用是增強協(xié)議的安全性眼虱。但數(shù)據(jù)掩碼并不是為了保護數(shù)據(jù)本身席纽,因為算法本身是公開的捏悬,運算也不復雜。除了加密通道本身润梯,似乎沒有太多有效的保護通信安全的辦法过牙。
  • 那么為什么還要引入掩碼計算呢,除了增加計算機器的運算量外似乎并沒有太多的收益(這也是不少同學疑惑的點)纺铭。
  • 答案還是兩個字:安全寇钉。但并不是為了防止數(shù)據(jù)泄密,而是為了防止早期版本的協(xié)議中存在的代理緩存污染攻擊(proxy cache poisoning attacks)等問題舶赔。

參考

http://www.reibang.com/p/9c09c9a75e9c
http://www.reibang.com/p/867274a5e054
http://www.reibang.com/p/fc09b0899141

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末扫倡,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子竟纳,更是在濱河造成了極大的恐慌撵溃,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,042評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件锥累,死亡現(xiàn)場離奇詭異缘挑,居然都是意外死亡,警方通過查閱死者的電腦和手機桶略,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評論 2 384
  • 文/潘曉璐 我一進店門卖哎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人删性,你說我怎么就攤上這事亏娜。” “怎么了蹬挺?”我有些...
    開封第一講書人閱讀 156,674評論 0 345
  • 文/不壞的土叔 我叫張陵维贺,是天一觀的道長。 經(jīng)常有香客問我巴帮,道長溯泣,這世上最難降的妖魔是什么虐秋? 我笑而不...
    開封第一講書人閱讀 56,340評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮垃沦,結果婚禮上客给,老公的妹妹穿的比我還像新娘。我一直安慰自己肢簿,他們只是感情好靶剑,可當我...
    茶點故事閱讀 65,404評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著池充,像睡著了一般桩引。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上收夸,一...
    開封第一講書人閱讀 49,749評論 1 289
  • 那天坑匠,我揣著相機與錄音,去河邊找鬼卧惜。 笑死厘灼,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的咽瓷。 我是一名探鬼主播设凹,決...
    沈念sama閱讀 38,902評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼忱详!你這毒婦竟也來了?” 一聲冷哼從身側響起跺涤,我...
    開封第一講書人閱讀 37,662評論 0 266
  • 序言:老撾萬榮一對情侶失蹤匈睁,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后桶错,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體航唆,經(jīng)...
    沈念sama閱讀 44,110評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年院刁,在試婚紗的時候發(fā)現(xiàn)自己被綠了糯钙。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,577評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡退腥,死狀恐怖任岸,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情狡刘,我是刑警寧澤享潜,帶...
    沈念sama閱讀 34,258評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站嗅蔬,受9級特大地震影響剑按,放射性物質(zhì)發(fā)生泄漏疾就。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,848評論 3 312
  • 文/蒙蒙 一艺蝴、第九天 我趴在偏房一處隱蔽的房頂上張望猬腰。 院中可真熱鬧,春花似錦猜敢、人聲如沸姑荷。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽厢拭。三九已至,卻和暖如春撇叁,著一層夾襖步出監(jiān)牢的瞬間供鸠,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評論 1 264
  • 我被黑心中介騙來泰國打工陨闹, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留楞捂,地道東北人。 一個月前我還...
    沈念sama閱讀 46,271評論 2 360
  • 正文 我出身青樓趋厉,卻偏偏與公主長得像寨闹,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子君账,可洞房花燭夜當晚...
    茶點故事閱讀 43,452評論 2 348

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