IOS 原生網(wǎng)絡(luò)請求

用多了ASIHttpRequest與AFNetWorking第三方網(wǎng)絡(luò)框架難免對蘋果底層的網(wǎng)絡(luò)請求陌生堪遂,了解下蘋果網(wǎng)絡(luò)訪問相關(guān)知識

一响逢、URL Session的基本概念###

1.三種工作模式:
1)默認會話模式(default):工作模式類似于原來的NSURLConnection懈词,使用的是基于磁盤緩存的持久化策略,使用用戶keychain中保存的證書進行認證授權(quán)。
2)瞬時會話模式(ephemeral):該模式不使用磁盤保存任何數(shù)據(jù)。所有和會話相關(guān)的caches钙态,證書,cookies等都被保存在RAM中菇晃,因此當程序使會話無效册倒,這些緩存的數(shù)據(jù)就會被自動清空。
3)后臺會話模式(background):該模式在后臺完成上傳和下載磺送,在創(chuàng)建Configuration對象的時候需要提供一個NSString類型的ID用于標識完成工作的后臺會話驻子。
2.NSURLSession支持的三種任務(wù)
NSURLSession類支持三種類型的任務(wù):加載數(shù)據(jù)屈尼,下載和上傳。

二拴孤、相關(guān)的類###

NSURLConnection這個名字,實際上指的是一組構(gòu)成Foundation框架中URL加載系統(tǒng)的相互關(guān)聯(lián)的組件:NSURLRequest甲捏,NSURLResponse演熟,NSURLProtocol,NSURLCache司顿,NSHTTPCookieStorage芒粹,NSURLCredentialStorage,以及和它同名的NSURLConnection大溜。
在WWDC 2013中化漆,Apple的團隊對NSURLConnection進行了重構(gòu),并推出了NSURLSession作為替代钦奋。
NSURLSession也是一組相互依賴的類座云,它的大部分組件和NSURLConnection中的組件相同如NSURLRequest,NSURLCache等付材。而NSURLSession的不同之處在于朦拖,它將NSURLConnection替換為NSURLSession和NSURLSessionConfiguration,以及3個NSURLSessionTask的子類:NSURLSessionDataTask, NSURLSessionUploadTask, 和NSURLSessionDownloadTask厌衔。

關(guān)系圖

自己簡單封裝的網(wǎng)絡(luò)工具類
.h文件

//  XMNetWorkHelper.h
//  Created by 修么 on 16/11/28
//  Copyright ? 2016年 修么. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

typedef void (^XMCompletioBlock)(NSDictionary *dic, NSURLResponse *response, NSError *error);
typedef void (^XMSuccessBlock)(NSDictionary *data);
typedef void (^XMFailureBlock)(NSError *error);

@interface XMNetWorkHelper : NSObject

/**
 *  get請求
 */
+ (void)getWithUrlString:(NSString *)url parameters:(id)parameters success:(XMSuccessBlock)successBlock failure:(XMFailureBlock)failureBlock;

/**
 * post請求
 */
+ (void)postWithUrlString:(NSString *)url parameters:(id)parameters success:(XMSuccessBlock)successBlock failure:(XMFailureBlock)failureBlock;

.m文件

//
//  XMNetWorkHelper.m
//
//  Created by 修么 on 16/11/28.
//  Copyright ? 2016年 修么. All rights reserved.
//

#import "XMNetWorkHelper.h"

@implementation XMNetWorkHelper

//GET請求
+ (void)getWithUrlString:(NSString *)url parameters:(id)parameters success:(XMSuccessBlock)successBlock failure:(XMFailureBlock)failureBlock
{
    NSMutableString *mutableUrl = [[NSMutableString alloc] initWithString:url];
    if ([parameters allKeys]) {
        [mutableUrl appendString:@"?"];
        for (id key in parameters) {
            NSString *value = [[parameters objectForKey:key] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
            [mutableUrl appendString:[NSString stringWithFormat:@"%@=%@&", key, value]];
        }
    }
    NSString *urlEnCode = [[mutableUrl substringToIndex:mutableUrl.length - 1] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
    NSURLRequest *urlRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:urlEnCode]];
    NSURLSession *urlSession = [NSURLSession sharedSession];
    NSURLSessionDataTask *dataTask = [urlSession dataTaskWithRequest:urlRequest completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        if (error) {
            failureBlock(error);
        } else {
            NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
            successBlock(dic);
        }
    }];
    [dataTask resume];
}

//POST請求 使用NSMutableURLRequest可以加入請求頭
+ (void)postWithUrlString:(NSString *)url parameters:(id)parameters success:(XMSuccessBlock)successBlock failure:(XMFailureBlock)failureBlock
{
    NSURL *nsurl = [NSURL URLWithString:url];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:nsurl];
    //如果想要設(shè)置網(wǎng)絡(luò)超時的時間的話璧帝,可以使用下面的方法:
    //NSMutableURLRequest *mutableRequest=[NSMutableURLRequest requestWithURL:[NSURL URLWithString:url] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10];
    
    //設(shè)置請求類型
    request.HTTPMethod = @"POST";
    
    //將需要的信息放入請求頭 隨便定義了幾個
    [request setValue:@"xxx" forHTTPHeaderField:@"Authorization"];//token
    [request setValue:@"xxx" forHTTPHeaderField:@"Gis-Lng"];//坐標 lng
    [request setValue:@"xxx" forHTTPHeaderField:@"Gis-Lat"];//坐標 lat
    [request setValue:@"xxx" forHTTPHeaderField:@"Version"];//版本
    NSLog(@"POST-Header:%@",request.allHTTPHeaderFields);
    
    //把參數(shù)放到請求體內(nèi)
    NSString *postStr = [XMNetWorkHelper parseParams:parameters];
    request.HTTPBody = [postStr dataUsingEncoding:NSUTF8StringEncoding];
    
    NSURLSession *session = [NSURLSession sharedSession];
    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        if (error) { //請求失敗
            failureBlock(error);
        } else {  //請求成功
            NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
            successBlock(dic);
        }
    }];
    [dataTask resume];  //開始請求
}

//重新封裝參數(shù) 加入app相關(guān)信息
+ (NSString *)parseParams:(NSDictionary *)params
{
    NSMutableDictionary *parameters = [[NSMutableDictionary alloc] initWithDictionary:params];
    [parameters setValue:@"ios" forKey:@"client"];
    [parameters setValue:@"請?zhí)鎿Q版本號" forKey:@"auth_version"];
    NSString* phoneModel = @"獲取手機型號" ;
    NSString* phoneVersion = [[UIDevice currentDevice] systemVersion];//ios系統(tǒng)版本號
    NSString *system = [NSString stringWithFormat:@"%@(%@)",phoneModel, phoneVersion];
    [parameters setValue:system forKey:@"system"];
    NSDate *date = [NSDate date];
    NSTimeInterval timeinterval = [date timeIntervalSince1970];
    [parameters setObject:[NSString stringWithFormat:@"%.0lf",timeinterval] forKey:@"auth_timestamp"];//請求時間戳
    NSString *devicetoken = @"請?zhí)鎿QDeviceToken";
    [parameters setValue:devicetoken forKey:@"uuid"]
    NSLog(@"請求參數(shù):%@",parameters);    

    NSString *keyValueFormat;
    NSMutableString *result = [NSMutableString new];
    //實例化一個key枚舉器用來存放dictionary的key
   
   //加密處理 將所有參數(shù)加密后結(jié)果當做參數(shù)傳遞
   //parameters = @{@"i":@"加密結(jié)果 抽空加入"};
   
    NSEnumerator *keyEnum = [parameters keyEnumerator];
    id key;
    while (key = [keyEnum nextObject]) {
        keyValueFormat = [NSString stringWithFormat:@"%@=%@&", key, [params valueForKey:key]];
        [result appendString:keyValueFormat];
    }
    return result;
}

NSURLSession文件下載

//下載圖片
/**
 該下載方式不適合大文件下載,
 因為該方法需要等到文件下載完畢了富寿,
 才會回調(diào)completionHandler后面的block參數(shù)睬隶,
 然后才可以在這個block參數(shù)可以獲取location(文件下載緩存的路徑)、response(響應(yīng))页徐、error(錯誤信息)苏潜。
 這樣的話,對于大文件变勇,我們就無法實時的在下載過程中獲取文件的下載進度了窖贤。
 @param imgUrl 圖片地址
 */
- (void)downloadImgWithUrl:(NSString *)imgUrl{
    //1.創(chuàng)建會話對象
    NSURLSession *session = [NSURLSession sharedSession];
    
    //2.請求路徑
    NSURL *url = [NSURL URLWithString:imgUrl];
    
    //3.創(chuàng)建task
    //接受到數(shù)據(jù)之后內(nèi)部會直接寫入到沙盒里面
    //completionHandler location(文件下載緩存的路徑)、response(響應(yīng))贰锁、error(錯誤信息)
    NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithURL:url completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        if (error == nil) {
            //5.接受數(shù)據(jù)
            NSLog(@"%@",location);
            
            //5.1確定文件的全路徑
            NSString *fullPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:response.suggestedFilename];
            
            //5.2 剪切文件
            /*
             第一個參數(shù):要剪切的文件在哪里
             第二個參數(shù):目標地址
             第三個參數(shù):錯誤信息
             */
            NSError *fileError;
            [[NSFileManager defaultManager] moveItemAtURL:location toURL:[NSURL fileURLWithPath:fullPath] error:&fileError];
            //打印
            NSLog(@"%@---%@",fullPath,[NSThread currentThread]);
            if (fileError == nil) {
                NSLog(@"file save success");
            } else {
                NSLog(@"file save error: %@",fileError);
            }
        } else {
            NSLog(@"download error:%@",error);
        }

    }];
    
    //4.啟動task
    [downloadTask resume];
}

//下載視頻
- (void)downloadVideoWithUrl:(NSString *)videoUrl{
    //1.創(chuàng)建會話對象
    NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    
    //2.請求路徑
    NSURL *url = [NSURL URLWithString:videoUrl];
    
    //3.創(chuàng)建task
    NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithURL:url];
    
    //4.啟動task
    [downloadTask resume];
}

#pragma mark -NSURLSessionDownloadDelegate Function
// 下載數(shù)據(jù)的過程中會調(diào)用的代理方法
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite{
    NSLog(@"%lf",1.0 * totalBytesWritten / totalBytesExpectedToWrite);
}
// 重新恢復(fù)下載的代理方法
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes{
    
}
// 寫入數(shù)據(jù)到本地的時候會調(diào)用的方法
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
didFinishDownloadingToURL:(NSURL *)location{
    NSString* fullPath =
    [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject]
     stringByAppendingPathComponent:downloadTask.response.suggestedFilename];;
    [[NSFileManager defaultManager] moveItemAtURL:location
                                            toURL:[NSURL fileURLWithPath:fullPath]
                                            error:nil];
    NSLog(@"%@",fullPath);
}
// 請求完成赃梧,錯誤調(diào)用的代理方法
-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error{
    
}

** NSURLSession文件上傳**

//第1種方式 以流的方式上傳,大小理論上不受限制豌熄,但應(yīng)注意時間
-(void)uploadFileWithData:(NSData *)fileData{
    // 1.創(chuàng)建url 服務(wù)器上傳腳本
    NSString *urlString = @"http://服務(wù)端/upload.php";
    NSURL *url = [NSURL URLWithString:urlString];
    
    // 2.創(chuàng)建請求
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    // 文件上傳使用post
    request.HTTPMethod = @"POST";
    
    // 3.開始上傳   request的body data將被忽略授嘀,而由fromData提供
    [[[NSURLSession sharedSession] uploadTaskWithRequest:request fromData:fileData     completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        if (error == nil) {
            NSLog(@"upload success:%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
        } else {
            NSLog(@"upload error:%@",error);
        }
    }] resume];
}


//第2種方式 拼接表單的方式進行上傳
- (void)uploadWithFilePath:(NSString *)filePath withfileName:(NSString *)fileName {
    // 1.創(chuàng)建url  服務(wù)器上傳腳本
    NSString *urlString = @"http://服務(wù)器/upload.php";
    urlString = [urlString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLFragmentAllowedCharacterSet]];
    NSURL *url = [NSURL URLWithString:urlString];
    
    // 2.創(chuàng)建請求
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    // 文件上傳使用post
    request.HTTPMethod = @"POST";
    
    NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@",@"boundary"];
    
    [request setValue:contentType forHTTPHeaderField:@"Content-Type"];
    // 3.拼接表單,大小受MAX_FILE_SIZE限制(2MB)  FilePath:要上傳的本地文件路徑  formName:表單控件名稱锣险,應(yīng)于服務(wù)器一致
    NSData* data = [self getHttpBodyWithFilePath:filePath formName:@"file" reName:fileName];
    request.HTTPBody = data;
    // 根據(jù)需要是否提供蹄皱,非必須,如果不提供览闰,session會自動計算
    [request setValue:[NSString stringWithFormat:@"%lu",data.length] forHTTPHeaderField:@"Content-Length"];
    
    // 4.1 使用dataTask
    [[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        if (error == nil) {
            NSLog(@"upload success:%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
        } else {
            NSLog(@"upload error:%@",error);
        }
        
    }] resume];
#if 0
    // 4.2 開始上傳 使用uploadTask   fromData:可有可無,會被忽略
    [[[NSURLSession sharedSession] uploadTaskWithRequest:request fromData:nil     completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        if (error == nil) {
            NSLog(@"upload success:%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
        } else {
            NSLog(@"upload error:%@",error);
        }
    }] resume];
#endif
}

/// filePath:要上傳的文件路徑   formName:表單控件名稱  reName:上傳后文件名
- (NSData *)getHttpBodyWithFilePath:(NSString *)filePath formName:(NSString *)formName reName:(NSString *)reName
{
    NSMutableData *data = [NSMutableData data];
    NSURLResponse *response = [self getLocalFileResponse:filePath];
    // 文件類型:MIMEType  文件的大邢镎邸:expectedContentLength  文件名字:suggestedFilename
    NSString *fileType = response.MIMEType;
    
    // 如果沒有傳入上傳后文件名稱,采用本地文件名!
    if (reName == nil) {
        reName = response.suggestedFilename;
    }
    
    // 表單拼接
    NSMutableString *headerStrM =[NSMutableString string];
    [headerStrM appendFormat:@"--%@\r\n",@"boundary"];
    // name:表單控件名稱  filename:上傳文件名
    [headerStrM appendFormat:@"Content-Disposition: form-data; name=%@; filename=%@\r\n",formName,reName];
    [headerStrM appendFormat:@"Content-Type: %@\r\n\r\n",fileType];
    [data appendData:[headerStrM dataUsingEncoding:NSUTF8StringEncoding]];
    
    // 文件內(nèi)容
    NSData *fileData = [NSData dataWithContentsOfFile:filePath];
    [data appendData:fileData];
    
    NSMutableString *footerStrM = [NSMutableString stringWithFormat:@"\r\n--%@--\r\n",@"boundary"];
    [data appendData:[footerStrM  dataUsingEncoding:NSUTF8StringEncoding]];
    //    NSLog(@"dataStr=%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
    return data;
}
/// 獲取響應(yīng)压鉴,主要是文件類型和文件名
- (NSURLResponse *)getLocalFileResponse:(NSString *)urlString
{
    urlString = [urlString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLFragmentAllowedCharacterSet]];
    // 本地文件請求
    NSURL *url = [NSURL fileURLWithPath:urlString];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    
    __block NSURLResponse *localResponse = nil;
    // 使用信號量實現(xiàn)NSURLSession同步請求
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
    [[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        localResponse = response;
        dispatch_semaphore_signal(semaphore);
    }] resume];
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    return  localResponse;
}

//服務(wù)端PHP腳本

//以文件流的形式上傳文件
<?php
/** 二進制流生成文件
 * $_POST 無法解釋二進制流,需要用到 $GLOBALS['HTTP_RAW_POST_DATA'] 或 php://input
 * $GLOBALS['HTTP_RAW_POST_DATA'] 和 php://input 都不能用于 enctype=multipart/form-data
 * @param    String  $file   要生成的文件路徑
 * @return   boolean
 */
function binary_to_file($file){
    $content = $GLOBALS['HTTP_RAW_POST_DATA'];          // 需要php.ini設(shè)置
    if(empty($content)){
        $content = file_get_contents('php://input');    // 不需要php.ini設(shè)置锻拘,內(nèi)存壓力小
    }
    $ret = file_put_contents($file, $content, true);
    return $ret;
}
$file_dir="images/image.png";  // 固定的文件名,注意設(shè)置images文件夾權(quán)限為所有用戶可讀寫S涂浴!署拟!
binary_to_file($file_dir);
?>

//以表單形式上傳
<?php
header("Content-type: application/json; charset=utf-8");
// 配置文件需要上傳到服務(wù)器的路徑婉宰,需要允許所有用戶有可寫權(quán)限,否則無法上傳推穷!
$uploaddir = 'images/';
// file表單名稱心包,應(yīng)與客戶端一致
$uploadfile = $uploaddir . basename($_FILES['file']['name']);

move_uploaded_file($_FILES['file']['tmp_name'], $uploadfile);

echo json_encode($_FILES);
?>

NSURLSessionConfiguration###

NSURLConnection是全局性的,即它的配置對全局有效馒铃,如果有兩個鏈接需要不同的cookies蟹腾、證書這些公共資源,則NSURLConnection無法滿足要求区宇,這時NSURLSession的優(yōu)勢則體現(xiàn)出來岭佳,NSURLSession可以同過NSURLSessionConfiguration可以設(shè)置全局的網(wǎng)絡(luò)訪問屬性。

NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
// delegateQueue:請求完成回調(diào)函數(shù)和代理函數(shù)的運行線程萧锉,如果為nil則系統(tǒng)自動創(chuàng)建一個串行隊列珊随,不影響sessionTask的運行線程
NSURLSession *session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue mainQueue]];

三種會話方式:

  1. defaultSessionConfiguration:進程內(nèi)會話(默認會話),類似 NSURLConnection的標準配置柿隙,用硬盤來緩存數(shù)據(jù)叶洞。
  2. ephemeralSessionConfiguration:臨時的進程內(nèi)會話(內(nèi)存),不會將cookie禀崖、緩存儲存到本地衩辟,只會放到內(nèi)存中,當應(yīng)用程序退出后數(shù)據(jù)也會消失,可以用于實現(xiàn)“秘密瀏覽”
  3. backgroundSessionConfiguration:建立后臺會話可以在應(yīng)用程序掛起波附,退出艺晴,崩潰的情況下運行上傳和下載任務(wù),后臺另起一個線程掸屡。另外封寞,系統(tǒng)會根據(jù)設(shè)備的負載程度決定分配下載的資源,因此有可能會很慢甚至超時失敗仅财。

設(shè)置一些網(wǎng)絡(luò)屬性:

  • HTTPAdditionalHeaders:可以設(shè)置出站請求的數(shù)據(jù)頭
configuration.HTTPAdditionalHeaders = @{ 
    @"Accept": @"application/json",
    @"Accept-Language": @"en",
    @"Authorization": authString, 
    @"User-Agent": userAgentString
};
  • networkServiceType狈究,設(shè)置網(wǎng)絡(luò)服務(wù)類型
  • NSURLNetworkServiceTypeDefault 默認
  • NSURLNetworkServiceTypeVoIP VoIP
  • NSURLNetworkServiceTypeVideo 視頻
  • NSURLNetworkServiceTypeBackground 后臺
  • NSURLNetworkServiceTypeVoice 語音
  • allowsCellularAccess:允許蜂窩訪問
  • timeoutIntervalForRequest:請求的超時時長
  • requestCachePolicy:緩存策略

注意事項:如果是自定義會話并指定了代理,會話會對代理進行強引用,在視圖控制器銷毀之前盏求,需要取消網(wǎng)絡(luò)會話抖锥,否則會造成內(nèi)存泄漏

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末亿眠,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子磅废,更是在濱河造成了極大的恐慌纳像,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件拯勉,死亡現(xiàn)場離奇詭異竟趾,居然都是意外死亡,警方通過查閱死者的電腦和手機谜喊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來倦始,“玉大人斗遏,你說我怎么就攤上這事⌒兀” “怎么了诵次?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長枚碗。 經(jīng)常有香客問我逾一,道長,這世上最難降的妖魔是什么肮雨? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任遵堵,我火速辦了婚禮,結(jié)果婚禮上怨规,老公的妹妹穿的比我還像新娘陌宿。我一直安慰自己,他們只是感情好波丰,可當我...
    茶點故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布壳坪。 她就那樣靜靜地躺著,像睡著了一般掰烟。 火紅的嫁衣襯著肌膚如雪爽蝴。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天纫骑,我揣著相機與錄音蝎亚,去河邊找鬼。 笑死先馆,一個胖子當著我的面吹牛颖对,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播磨隘,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼缤底,長吁一口氣:“原來是場噩夢啊……” “哼顾患!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起个唧,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤江解,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后徙歼,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體犁河,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年魄梯,在試婚紗的時候發(fā)現(xiàn)自己被綠了桨螺。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡酿秸,死狀恐怖灭翔,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情辣苏,我是刑警寧澤肝箱,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站稀蟋,受9級特大地震影響煌张,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜退客,卻給世界環(huán)境...
    茶點故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一专控、第九天 我趴在偏房一處隱蔽的房頂上張望楣责。 院中可真熱鬧兜叨,春花似錦缓窜、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至刷允,卻和暖如春冤留,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背树灶。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工纤怒, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人天通。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓泊窘,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子烘豹,可洞房花燭夜當晚...
    茶點故事閱讀 42,786評論 2 345

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