iOS中長連接的那些事

我們組內(nèi)部搞了一個(gè)公眾號,大家支持一下善炫,有不少好文章。iOS中長連接的那些事

一美澳、長連接在iOS開發(fā)中的作用

一般的App的網(wǎng)絡(luò)請求都是基于Http1.0進(jìn)行的销部,使用的是NSURLConnection摸航、NSURLSession或者是AFNetworking制跟,Http1.0鏈接最顯著的特點(diǎn)就是客戶端每一次需要主動向服務(wù)端發(fā)送請求,都需要經(jīng)歷建立鏈接酱虎、發(fā)送請求雨膨、返回?cái)?shù)據(jù)、關(guān)閉鏈接這幾個(gè)階段读串,是一種單向請求且無狀態(tài)的協(xié)議聊记。而有的時(shí)候撒妈,我們需要服務(wù)端主動往客戶端進(jìn)行推送服務(wù)的時(shí)候,這個(gè)時(shí)候長連接就起作用了排监。蘋果提供的push服務(wù)apns就是典型的長連接的應(yīng)用狰右,IM應(yīng)用、訂單推送這些也是長連接的典型應(yīng)用舆床。長連接的特點(diǎn)是一旦通過三次握手建立鏈接之后棋蚌,該條鏈路就一直存在,而且該鏈路是一種雙向的通行機(jī)制挨队,適合于頻繁的網(wǎng)絡(luò)請求谷暮,避免Http每一次請求都會建立鏈接和關(guān)閉鏈接的操作,減少浪費(fèi)盛垦,提高效率湿弦。

二、通信網(wǎng)絡(luò)的一些基本概念

長連接的一般實(shí)現(xiàn)方式都是基于TCP或者UDP協(xié)議完成的腾夯。這個(gè)時(shí)候我們就需要一些基本的通信網(wǎng)絡(luò)概念颊埃。

2.1 OSI七層網(wǎng)絡(luò)協(xié)議

開放系統(tǒng)互連參考模型 (Open System Interconnect 簡稱OSI)是國際標(biāo)準(zhǔn)化組織(ISO)和國際電報(bào)電話咨詢委員會(CCITT)聯(lián)合制定的開放系統(tǒng)互連參考模型,為開放式互連信息系統(tǒng)提供了一種功能結(jié)構(gòu)的框架俯在。


image
  • 物理層:負(fù)責(zé)機(jī)械竟秫、電子、定時(shí)接口通信信道上的原始比特流的傳輸跷乐。
  • 數(shù)據(jù)鏈路層:負(fù)責(zé)物理尋址肥败,同時(shí)將原始比特流轉(zhuǎn)變成邏輯傳輸線路。
  • 網(wǎng)絡(luò)層:控制子網(wǎng)的運(yùn)行愕提,如邏輯編址馒稍、分組傳輸、路由選擇浅侨。
  • 傳輸層:接受上一層的數(shù)據(jù)纽谒,在必要的時(shí)候把數(shù)據(jù)進(jìn)行分割,并將這些數(shù)據(jù)交給網(wǎng)絡(luò)層如输,且保證這些數(shù)據(jù)段有效到達(dá)對方鼓黔。
  • 會話層:不同機(jī)器上的用戶之間建立以及管理回話。
  • 表示層:信息的語法語義以及它們的關(guān)聯(lián)不见,如加密解密澳化、轉(zhuǎn)換翻譯、壓縮解壓縮稳吮。
  • 應(yīng)用層:各種應(yīng)用程序協(xié)議缎谷,如Http、Ftp灶似、SMTP列林、POP3瑞你。

2.2、IP希痴、TCP和Http

本文主要講一下在網(wǎng)絡(luò)層的IP協(xié)議者甲、傳輸層的TCP協(xié)議和應(yīng)用層的Http協(xié)議。這也是我們平時(shí)接觸到最多的三個(gè)網(wǎng)絡(luò)協(xié)議砌创。

  • IP協(xié)議:TCP/IP 中的 IP 是網(wǎng)絡(luò)協(xié)議 (Internet Protocol) 的縮寫过牙。從字面意思便知,它是互聯(lián)網(wǎng)眾多協(xié)議的基礎(chǔ)纺铭。IP 實(shí)現(xiàn)了分組交換網(wǎng)絡(luò)寇钉。在協(xié)議下,機(jī)器被叫做 主機(jī) (host)舶赔,IP 協(xié)議明確了 host 之間的資料包(數(shù)據(jù)包)的傳輸方式扫倡。所謂數(shù)據(jù)包是指一段二進(jìn)制數(shù)據(jù),其中包含了發(fā)送源主機(jī)和目標(biāo)主機(jī)的信息竟纳。IP 網(wǎng)絡(luò)負(fù)責(zé)源主機(jī)與目標(biāo)主機(jī)之間的數(shù)據(jù)包傳輸撵溃。IP 協(xié)議的特點(diǎn)是 best effort(盡力服務(wù),其目標(biāo)是提供有效服務(wù)并盡力傳輸)。這意味著,在傳輸過程中觅捆,數(shù)據(jù)包可能會丟失,也有可能被重復(fù)傳送導(dǎo)致目標(biāo)主機(jī)收到多個(gè)同樣的數(shù)據(jù)包语淘。
  • TCP協(xié)議:TCP 層位于 IP 層之上,是最受歡迎的因特網(wǎng)通訊協(xié)議之一际歼,人們通常用 TCP/IP 來泛指整個(gè)因特網(wǎng)協(xié)議族惶翻。剛剛提到,IP 協(xié)議允許兩個(gè)主機(jī)之間傳送單一數(shù)據(jù)包鹅心。為了保證對所傳送數(shù)據(jù)包達(dá)到盡力服務(wù)的目的吕粗,最終的傳輸?shù)慕Y(jié)果可能是數(shù)據(jù)包亂序、重復(fù)甚至丟包旭愧。TCP 是基于 IP 層的協(xié)議颅筋。但是 TCP 是可靠的、有序的输枯、有錯(cuò)誤檢查機(jī)制的基于字節(jié)流傳輸?shù)膮f(xié)議议泵。這樣當(dāng)兩個(gè)設(shè)備上的應(yīng)用通過 TCP 來傳遞數(shù)據(jù)的時(shí)候,總能夠保證目標(biāo)接收方收到的數(shù)據(jù)的順序和內(nèi)容與發(fā)送方所發(fā)出的是一致的用押。TCP 做的這些事看起來稀松平常肢簿,但是比起 IP 層的粗曠處理方式已經(jīng)是有顯著的進(jìn)步了靶剑。應(yīng)用程序之間可以通過 TCP 建立鏈接蜻拨。TCP 建立的是雙向連接池充,通信雙方可以同時(shí)進(jìn)行數(shù)據(jù)的傳輸。連接的雙方都不需要操心數(shù)據(jù)是否分塊缎讼,或者是否采用了盡力服務(wù)等收夸。TCP 會確保所傳輸?shù)臄?shù)據(jù)的正確性,即接受方收到的數(shù)據(jù)與發(fā)出方的數(shù)據(jù)一致血崭。
  • HTTP協(xié)議:HTTP 是典型的 TCP 應(yīng)用卧惜。用戶瀏覽器(應(yīng)用 1)與 web 服務(wù)器(應(yīng)用 2)建立連接后,瀏覽器可以通過連接發(fā)送服務(wù)請求夹纫,web 服務(wù)器可以通過同樣的連接對請求做出響應(yīng)咽瓷。1989 年,Tim Berners Lee 在 CERN(European Organization for Nuclear Research 歐洲原子核研究委員會) 擔(dān)任軟件咨詢師的時(shí)候舰讹,開發(fā)了一套程序茅姜,奠定了萬維網(wǎng)的基礎(chǔ)。HyperText Transfer Protocol(超文本轉(zhuǎn)移協(xié)議月匣,即HTTP)是用于從 WWW 服務(wù)器傳輸超文本到本地瀏覽器的傳送協(xié)議钻洒。HTTP 采用簡單的請求和響應(yīng)機(jī)制。在 Safari 輸入 http://www.apple.com 時(shí)锄开,會向 www.appple.com 所在的服務(wù)器發(fā)送一個(gè) HTTP 請求素标。服務(wù)器會對請求做出一個(gè)響應(yīng),將請求結(jié)果信息返回給 Safari萍悴。每一個(gè)請求都有一個(gè)對應(yīng)的響應(yīng)信息头遭。請求和響應(yīng)遵從同樣的格式。第一行是請求行或者響應(yīng)狀態(tài)行癣诱。接下來是 header 信息任岸,header 信息之后會有一個(gè)空行〗屏酰空行之后是 body 請求信息體享潜。

三、Socket

socket翻譯為套接字嗅蔬,是支持TCP/IP協(xié)議的網(wǎng)絡(luò)通信的基本操作單元剑按。它是網(wǎng)絡(luò)通信過程中端點(diǎn)的抽象表示,包含進(jìn)行網(wǎng)絡(luò)通信必須的五種信息:連接使用的協(xié)議澜术,本地主機(jī)的IP地址艺蝴,本地進(jìn)程的協(xié)議端口,遠(yuǎn)地主機(jī)的IP地址鸟废,遠(yuǎn)地進(jìn)程的協(xié)議端口猜敢。socket是在應(yīng)用層和傳輸層之間的一個(gè)抽象層,它把TCP/IP層復(fù)雜的操作抽象為幾個(gè)簡單的接口供應(yīng)用層調(diào)用已實(shí)現(xiàn)進(jìn)程在網(wǎng)絡(luò)中通信。它不屬于OSI七層協(xié)議缩擂,它只是對于TCP鼠冕,UDP協(xié)議的一套封裝,讓我們開發(fā)人員更加容易編寫基于TCP胯盯、UDP的應(yīng)用懈费。


image

使用socket進(jìn)行TCP通信的基本流程如下:


socket編程中我們經(jīng)常使用到的函數(shù)

// socket()函數(shù)用于根據(jù)指定的地址族、數(shù)據(jù)類型和協(xié)議來分配一個(gè)套接口的描述字及其所用的資源博脑。如果協(xié)議protocol未指定(等于0), 則使用缺省的連接方式憎乙。
socket(af,type,protocol)

// 將一本地地址與一套接口捆綁。本函數(shù)適用于未連接的數(shù)據(jù)報(bào)或流類套接口叉趣,在connect()或listen()調(diào)用前使用泞边。當(dāng)用socket()創(chuàng)建套接口后,它便存在于一個(gè)名字空間(地址族)中疗杉,但并未賦名繁堡。bind()函數(shù)通過給一個(gè)未命名套接口分配一個(gè)本地名字來為套接口建立本地捆綁(主機(jī)地址/端口號).
bind(sockid, local addr, addrlen)

// 創(chuàng)建一個(gè)套接口并監(jiān)聽申請的連接.
listen( Sockid ,quenlen)

// 用于建立與指定socket的連接.
connect(sockid, destaddr, addrlen)

// 在一個(gè)套接口接受一個(gè)連接.
accept(Sockid,Clientaddr, paddrlen)

// 用于向一個(gè)已經(jīng)連接的socket發(fā)送數(shù)據(jù)乡数,如果無錯(cuò)誤椭蹄,返回值為所發(fā)送數(shù)據(jù)的總數(shù),否則返回SOCKET_ERROR净赴。
send(sockid, buff, bufflen) 

// 用于已連接的數(shù)據(jù)報(bào)或流式套接口進(jìn)行數(shù)據(jù)的接收绳矩。
recv()

// 指向一指定目的地發(fā)送數(shù)據(jù),sendto()適用于發(fā)送未建立連接的UDP數(shù)據(jù)包 (參數(shù)為SOCK_DGRAM)
sendto(sockid,buff,…,addrlen) 

// 用于從(已連接)套接口上接收數(shù)據(jù)玖翅,并捕獲數(shù)據(jù)發(fā)送源的地址翼馆。
recvfrom()

// 關(guān)閉Socket連接
close(socked)

四、實(shí)現(xiàn)一個(gè)簡單的基于TCP的Socket通信Demo

4.1金度、客戶端實(shí)現(xiàn)代碼

    // 1应媚、 創(chuàng)建socket
    /**
     參數(shù)
     domain: 協(xié)議域,AF_INET --> IPV4
     type: Socket 類型猜极, SOCK_STREAM(TCP)/SOCKET_DGRAM(報(bào)文 UDP)
     protocol: IPPROTO_TCP中姜,如果傳入0,會自動根據(jù)第二個(gè)參數(shù)跟伏,選擇合適的協(xié)議
     
     返回值
     socket
     */
    int clientSocket = socket(AF_INET, SOCK_STREAM, 0);
    
    // 2丢胚、 連接到服務(wù)器
    /**
     參數(shù)
     1> 客戶端socket
     2> 指向數(shù)據(jù)結(jié)構(gòu)sockaddr的指針,其中包括目的端口和IP地址
     3> 結(jié)構(gòu)體數(shù)據(jù)長度
     
     返回值
     0 成功/其他 錯(cuò)誤代號
     */
    struct sockaddr_in serverAddr;
    serverAddr.sin_family = AF_INET;
    //端口
    serverAddr.sin_port = htons(12345);
    //地址
    serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
    
    int connResult = connect(clientSocket, (const struct sockaddr *)&serverAddr, sizeof(serverAddr));
    if (connResult == 0) {
        NSLog(@"連接成功");
    }else{
        NSLog(@"連接失敗 %zi",connResult);
        return;
    }
    
    // 3受扳、發(fā)送數(shù)據(jù)到服務(wù)器
    /**
     參數(shù)
     1> 客戶端socket
     2> 發(fā)送內(nèi)容地址
     3> 發(fā)送內(nèi)容長度
     4> 發(fā)送方式標(biāo)志携龟,一般為0
     返回值
     如果成功,則返回發(fā)送的字節(jié)數(shù)勘高,失敗則返回SOCKET_ERROR
     */
    NSString *sendMsg = @"Hello";
    ssize_t sendLen = send(clientSocket, sendMsg.UTF8String, strlen(sendMsg.UTF8String), 0);
    NSLog(@"發(fā)送了 %zi 個(gè)字節(jié)",sendLen);
    
    
    // 4峡蟋、 從服務(wù)器接受數(shù)據(jù)
    /**
     參數(shù)
     1> 客戶端socket
     2> 接受內(nèi)容緩沖區(qū)地址
     3> 接受內(nèi)容緩沖區(qū)長度
     4> 接收方式坟桅,0表示阻塞,必須等待服務(wù)器返回?cái)?shù)據(jù)
     返回值
     如果成功蕊蝗,則返回讀入的字節(jié)數(shù)仅乓,失敗則返回SOCKET_ERROR
     */
    uint8_t buffer[1024];//將空間準(zhǔn)備出來
    
    ssize_t recvLen = recv(clientSocket, buffer, sizeof(buffer), 0);
    NSLog(@"接收到了 %zi 個(gè)字節(jié)",recvLen);
    
    NSData *data = [NSData dataWithBytes:buffer length:recvLen];
    NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    NSLog(@"接收到數(shù)據(jù)為 %@",str);
    
    // 5、 關(guān)閉
    close(clientSocket);

4.2匿又、服務(wù)端Socket使用nc命令代替

打開mac命令行終端 輸入 nc -lk 12345

4.3、演示結(jié)果

image

五建蹄、CocoaAsyncSocket

CocoaAsyncSocket是谷歌基于BSD-Socket寫的一個(gè)IM框架碌更,它給Mac和iOS提供了易于使用的、強(qiáng)大的異步套接字庫洞慎,向上封裝出簡單易用OC接口痛单。省去了我們面向Socket以及數(shù)據(jù)流Stream等繁瑣復(fù)雜的編程,而且支持TCP或者UDP協(xié)議劲腿,支持IPv4和IPv6旭绒,支持TLS/SSL安全傳輸,并且是線程安全的焦人。開源項(xiàng)目地址為https://github.com/robbiehanson/CocoaAsyncSocket挥吵。

5.1、基于CocoaAsyncSocket實(shí)現(xiàn)的客戶端代碼

#import "GCDAsyncSocket.h"

@interface ViewController2 ()<GCDAsyncSocketDelegate>

@property (nonatomic, strong) GCDAsyncSocket *clientSocket;

@end

@implementation ViewController2

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor redColor];
    UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(0, 400, 300, 60)];
    btn.backgroundColor = [UIColor orangeColor];
    [btn setTitle:@"發(fā)送數(shù)據(jù)" forState:UIControlStateNormal];
    [btn addTarget:self action:@selector(clickBtn) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:btn];
    
    self.clientSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
    
    NSError *error = nil;
    [self.clientSocket connectToHost:@"127.0.0.1" onPort:12345 error:&error];
    if (error) {
        NSLog(@"error == %@",error);
    }
}

- (void)clickBtn{
    NSString *msg = @"發(fā)送數(shù)據(jù): 你好\r\n";
    NSData *data = [msg dataUsingEncoding:NSUTF8StringEncoding];
    // withTimeout -1 : 無窮大,一直等
    // tag : 消息標(biāo)記
    [self.clientSocket writeData:data withTimeout:-1 tag:0];
}

- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port
{
    NSLog(@"鏈接成功");
    NSLog(@"服務(wù)器IP: %@-------端口: %d",host,port);
}

- (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag
{
    NSLog(@"發(fā)送數(shù)據(jù) tag = %zi",tag);
    [sock readDataWithTimeout:-1 tag:tag];
}

- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
{
    NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    NSLog(@"讀取數(shù)據(jù) data = %@ tag = %zi",str,tag);
    // 讀取到服務(wù)端數(shù)據(jù)值后,能再次讀取
    [sock readDataWithTimeout:- 1 tag:tag];

}

- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err
{
    NSLog(@"斷開連接");
    self.clientSocket.delegate = nil;
    self.clientSocket = nil;
}
@end

5.2花椭、服務(wù)端Socket使用nc命令代替

打開mac命令行終端 輸入 nc -lk 12345

5.3忽匈、演示結(jié)果

六、補(bǔ)充知識

6.1矿辽、長連接為什么要保持心跳丹允?

國內(nèi)移動無線網(wǎng)絡(luò)運(yùn)營商在鏈路上一段時(shí)間內(nèi)沒有數(shù)據(jù)通訊后, 會淘汰NAT表中的對應(yīng)項(xiàng), 造成鏈路中斷。而國內(nèi)的運(yùn)營商一般NAT超時(shí)的時(shí)間為5分鐘袋倔,所以通常我們心跳設(shè)置的時(shí)間間隔為3-5分鐘雕蔽。

6.2、長連接選擇TCP協(xié)議還是UDP協(xié)議宾娜?

使用TCP進(jìn)行數(shù)據(jù)傳輸?shù)脑捙唵巍踩八⒖煽考窒荩菐淼氖欠?wù)端承載壓力比較大。

使用UDP進(jìn)行數(shù)據(jù)傳輸?shù)脑捴龈时容^高髓废,帶來的服務(wù)端壓力較小,但是需要自己保證數(shù)據(jù)的可靠性该抒,不作處理的話慌洪,會導(dǎo)致丟包顶燕、亂序等問題。

如果你的技術(shù)團(tuán)隊(duì)實(shí)力過硬冈爹,你可以選擇UDP協(xié)議涌攻,否則還是使用TCP協(xié)議比較好。據(jù)說騰訊IM就是使用的UDP協(xié)議频伤,然后還封裝了自己的私有協(xié)議恳谎,來保證UDP數(shù)據(jù)包的可靠傳輸。

6.3憋肖、服務(wù)端單機(jī)最大TCP連接數(shù)是多少因痛?

理論最大值:server通常固定在某個(gè)本地端口上監(jiān)聽,等待client的連接請求岸更。不考慮地址重用的情況下鸵膏,即使server端有多個(gè)ip,本地監(jiān)聽端口也是獨(dú)占的怎炊,因此server端tcp連接4元組中只有remote ip(也就是client ip)和remote port(客戶端port)是可變的谭企,因此最大tcp連接為客戶端ip數(shù)×客戶端port數(shù),對IPV4评肆,不考慮ip地址分類等因素债查,最大tcp連接數(shù)約為2的32次方(ip數(shù))×2的16次方(port數(shù)),也就是server端單機(jī)最大tcp連接數(shù)約為2的48次方瓜挽。

實(shí)際最大值:上面給出的是理論上的單機(jī)最大連接數(shù)攀操,在實(shí)際環(huán)境中,受到機(jī)器資源秸抚、操作系統(tǒng)等的限制速和,特別是sever端,其最大并發(fā)tcp連接數(shù)遠(yuǎn)不能達(dá)到理論上限剥汤。在unix/linux下限制連接數(shù)的主要因素是內(nèi)存和允許的文件描述符個(gè)數(shù)(每個(gè)tcp連接都要占用一定內(nèi)存颠放,每個(gè)socket就是一個(gè)文件描述符),另外1024以下的端口通常為保留端口吭敢。對server端碰凶,通過增加內(nèi)存、修改最大文件描述符個(gè)數(shù)等參數(shù)鹿驼,單機(jī)最大并發(fā)TCP連接數(shù)超過10萬,甚至上百萬 是沒問題的欲低,國外 Urban Airship 公司在產(chǎn)品環(huán)境中已做到 50 萬并發(fā) 。在實(shí)際應(yīng)用中畜晰,對大規(guī)模網(wǎng)絡(luò)應(yīng)用砾莱,還需要考慮C10K ,C100k問題凄鼻。

七腊瑟、參考文章

IP聚假,TCP 和 HTTP
玩轉(zhuǎn)iOS開發(fā):iOS中的Socket編程
iOS即時(shí)通訊,從入門到“放棄”
單機(jī)最大tcp連接數(shù)

八闰非、聯(lián)系方式

新浪微博
github
簡書首頁

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末膘格,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子财松,更是在濱河造成了極大的恐慌瘪贱,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件辆毡,死亡現(xiàn)場離奇詭異菜秦,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)胚迫,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進(jìn)店門喷户,熙熙樓的掌柜王于貴愁眉苦臉地迎上來唾那,“玉大人访锻,你說我怎么就攤上這事∧只瘢” “怎么了期犬?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長避诽。 經(jīng)常有香客問我龟虎,道長,這世上最難降的妖魔是什么沙庐? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任鲤妥,我火速辦了婚禮,結(jié)果婚禮上拱雏,老公的妹妹穿的比我還像新娘棉安。我一直安慰自己,他們只是感情好铸抑,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布贡耽。 她就那樣靜靜地躺著,像睡著了一般鹊汛。 火紅的嫁衣襯著肌膚如雪蒲赂。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天刁憋,我揣著相機(jī)與錄音滥嘴,去河邊找鬼。 笑死至耻,一個(gè)胖子當(dāng)著我的面吹牛氏涩,可吹牛的內(nèi)容都是我干的届囚。 我是一名探鬼主播,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼是尖,長吁一口氣:“原來是場噩夢啊……” “哼意系!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起饺汹,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤蛔添,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后兜辞,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體迎瞧,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年逸吵,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了凶硅。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 37,997評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡扫皱,死狀恐怖足绅,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情韩脑,我是刑警寧澤氢妈,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布,位于F島的核電站段多,受9級特大地震影響首量,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜进苍,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一加缘、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧觉啊,春花似錦拣宏、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至搜吧,卻和暖如春市俊,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背滤奈。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工摆昧, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蜒程。 一個(gè)月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓绅你,卻偏偏與公主長得像伺帘,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子忌锯,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評論 2 345

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