TCP连接:
建立一个TCP连接需要经过三次握手: 1.客户端向服务器发送syn包; 2.服务器收到syn包后回发syn+ack包 3.客户端收到syn+ack包,向服务器发送ack包 理想状态TCP连接一旦建立,任一方主动关闭连接前,TCP连接一直保持下去。服务器客户端均可发送断开TCP连接请求,断开需要四次握手HTTP连接:
客户端发送每次请求都需要服务器回送相应,请求结束后主动释放链接(即为短链接)。称为一次连接 通过保持每隔一段固定时间相互通讯,可确认彼此网络状态SOCKET(套接字)原理:
包含进行网络通讯的五种信息: 1.连接使用的协议 2.本地主机IP地址 3.本地进程协议端口 4.远地主机IP地址 5.远地进程协议端口 数据通讯时,TCP会遇到多个应用程序进程提供并发服务的问题,也就是多个TCP连接或多个应用程序进程要通过同一个TCP协议端口传输数据。 因此为应用程序与TCP/IP协议交互提供套接字(socket)接口区分来自不同应用程序进程或网络连接的通信,实现数据传输的并发服务创建socket连接时可指定传输协议(TCP或UDP),
当使用TCP协议进行连接,该socket连接就是一个TCP连接 当socket连接为TCP连接类型时,连接会长时间保持,但因客户端到服务器端之间的通讯需穿越多个中间节点如路由器,网关,防火墙等,防火墙默认会 关闭长时间处于非活跃状态的连接导致socket连接断开,因此需轮询告诉网络,连接处于活跃状态 建立socket连接: 需要至少一对套接字, 一个运行于客户端, 一个运行于服务器端 连接过程分三个步骤: 1.服务器监听:服务器端套接字处于等待连接状态,实时监听网络状态等待客户端连接请求 2.客户端请求:客户端套接字提出连接请求,连接服务器端套接字 因此客户端套接字需先描述目标服务器套接字的地址与端口号,然后提出连接请求 3.连接确认:服务器端套接字接收到连接请求,相应请求,建立新线程,把服务器端套接字的描述发给客户端 客户端确认此描述后双方真实建立连接,而服务器端套接字继续监听状态,继续接收其他客户端套接字的连接请求GET(参数暴露在url中,请求的接口会包含参数部分,参数会作为网址的一部分,服务器地址与参数之间通过 ? 来间隔。):
同步GET: 1.将网址初始化为OC字符串: NSString *urlStr=[NSString stringWithFormat:@"%@?query=%@&ion=%@&output=json&ak=6E823f587c95f0148c19993539b99295",baseInfoURL,@"银行",@"济南"]; 如果网址中存在中文,进行URLEncode NSString *newUrlStr=[urlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; 2.构建网络URL对象,NSURL NSURL *url=[NSURL URLWithString:newUrlStr]; 3.创建网络请求(默认GET方式) NSURLRequest *request=[NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:10]; 4.创建同步链接 NSURLResponse *response=nil; NSError *error=nil; NSData *data=[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error]; NSLog(@"请求文件总大小为:%lld",response.expectedContentLength); 异步GET: 1.将网址初始化为OC字符串: NSString *urlStr=[NSString stringWithFormat:@"%@?query=%@&ion=%@&output=json&ak=6E823f587c95f0148c19993539b99295",baseInfoURL,@"银行",@"济南"]; 如果网址中存在中文,进行URLEncode NSString *newUrlStr=[urlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; 2.构建网络URL对象,NSURL NSURL *url=[NSURL URLWithString:newUrlStr]; 3.创建网络请求 NSURLRequest *request=[NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:10]; 4.创建异步链接://以block回调方式(与代理回调方式互斥) [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLRequest *response,NSData *data,NSError *connectionError){ self.imageView.image=[UIImage imageWithData:data]; NSDictionary *dic=[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil]; NSLog(@"%@",dic); NSLog(@"请求文件总大小为:%lld",response.expectedContentLength); }];POST(参数封装在body请求体中,请求会将服务器地址与参数分开,请求接口中只有服务器地址,而参数会作为请求的一部分,提交后台服务器。):
同步POST: 1.根据网址初始化OC字符串对象 NSString *urlStr=[NSString stringWithFormat:@"%@",kVideoUrl]; 2.创建NSURL对象 NSURL *url=[NSURL URLWithString:urlStr]; 3.创建请求 NSMutableURLRequest *request=[NSMutableURLRequest requestWithURL:url]; 4.创建参数字符串对象 NSString *parmStr=[NSString stringWithFormat:@"username=%@&pwd=%@",_userName,_pwd]; 5.将字符串转为NSData对象 NSData *pramData=[parmStr dataUsingEncoding:NSUTF8StringEncoding]; 6.设置请求头,众多设置属性,此处简介Range属性,设置请求头Range可以指定请求下载数据包的某一部分实现断点下载 Range示例: bytes=0-499 //从0到499个字节数据 bytes=500- //从500字节以后的所有字节 bytes=-500 //最后500个字节 bytes=500-599,800-900 //同时指定几个范围 NSString *value=[NSString stringWithFormat:@"%lld",(long long)currentLength]; [request setHTTPHeaderField:@"Range"]; 7.设置请求体 [request setHTTPBody:pramData]; 8.设置请求方式 [request setHTTPMethod:@"POST"]; 9.创建同步链接 NSData *data=[NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil]; 异步POST: 1.根据网址初始化OC字符串对象 NSString *urlStr=[NSString stringWithFormat:@"%@",kVideoUrl]; 2.创建NSURL对象 NSURL *url=[NSURL URLWithString:urlStr]; 3.创建请求 NSMutableURLRequest *request=[NSMutableURLRequest requestWithURL:url]; 4.创建参数字符串对象 NSString *parmStr=[NSString stringWithFormat:@"username=%@&pwd=%@",_userName,_pwd]; 5.将字符串转为NSData对象 NSData *pramData=[parmStr dataUsingEncoding:NSUTF8StringEncoding]; 6.设置请求体 [request setHTTPBody:pramData]; 7.设置请求方式 [request setHTTPMethod:@"POST"];//setTimeoutInterval://设置超时 8.创建异步链接//以代理回调方式(与block回调方式互斥) [NSURLConnection connectionWithRequest:request delegate:self]; NSURLConnectionDataDelegate常用方法: 1.服务器接收到请求时 -(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{ 获取请求的完整数据长度 long long sumLength=response.expectedContentLength; } 2.当收到服务器返回的数据时,返回的可能是资源片段,可能多次调用 -(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{}
3.当服务器返回所有数据时,数据返回完毕 -(void)connectionDidFinishLoading:(NSURLConnection *)connection{}
4.请求数据失败时 -(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{ NSLog(@"%s",__FUNCTION__); }缓存连接所请求数据:
使用原则:假如某连接所返回的数据 1.经常更新:不能用缓存,比如股票数据 2.一成不变:果断用缓存 3.偶尔更新:定期更换缓存或清除缓存 缓存原理: 一个NSURLRequest对应一个NSCachedURLResponse 缓存方式: 1.内存缓存(程序关闭后缓存消失) 2.磁盘缓存(程序没有关闭时数据既在内存缓存,又在磁盘缓存) NSURLCache常用方法: 1.获取全局缓存: NSURLCache *cache=[NSURLCache sharedURLCache]; 2.设置内存缓存最大容量(单位字节,默认512KB) -(void)setMemoryCapacity:(NSUInteger)memoryCapacity; 3.设置磁盘缓存最大容量(单位字节,默认10M) -(void)setDiskCapacity:(NSUInteger)diskCapacity; 4.磁盘缓存的位置: 沙盒/Library/Caches 5.取出某个请求的缓存 -(NSCachedURLResponse *)cachedResponseForRequest:(NSURLRequest *)request; 6.清除某个请求的缓存 -(void)removeCachedResponseForRequest:(NSURLRequest *)request; 7.清除全部缓存 -(void)removeAllCachedResponses; 使用步骤: 1.首次请求该连接数据的时候设置请求的缓存策略 2.再次需要请求数据时,自动使用缓存数据即可 使用示范: 1.创建请求 NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; 2.设置该请求的缓存策略 request.cachePolicy = NSURLRequestReturnCacheDataElseLoad; 其中对NSURLRequest请求对象提供了能用的四种缓存策略: 1.默认的缓存策略(取决于协议) NSURLRequestUseProtocolCachePolicy 2.忽略缓存,重新请求 NSURLRequestReloadIgnoringLocalCacheData 3.有缓存就用缓存,没有缓存就重新请求 NSURLRequestReturnCacheDataElseLoad 4.有缓存就用缓存,没有缓存就不发请求,当做请求出错处理(用于离线模式) NSURLRequestReturnCacheDataDontLoad 数据上传:NSURLSession:
使用流程: NSURL-->NSURLRequest-->NSURLSessionConfiguration-->NSURLSession-->NSURLSessionTask-->resume-->block || delegate 配置工作模式NSURLSessionConfiguration,用于配置会话的属性,共3种: 1.默认会话模式:defaultSessionConfiguration 基于磁盘缓存的持久化策略,可进行认证授权 获取对象方法 +(NSURLSessionConfiguration *)defaultSessionConfiguration; 2.瞬时会话模式:ephemeralSessionConfiguration 不使用磁盘保存数据,所有与会话相关数据存于内存中 获取对象方法 + (NSURLSessionConfiguration *)ephemeralSessionConfiguration; 3.后台会话模式:backgroundSessionConfiguration 在后台完成上传和下载,创建NSURLSessionConfiguration对象时需提供一个NSString类型的ID用于标识完成工作的后台会话 获取对象方法 + (NSURLSessionConfiguration *)backgroundSessionConfiguration:(NSString *)identifier; 主要属性: BOOL allowsCellularAccess:指定是否允许使用蜂窝连接 BOOL discretionary:指定当程序在后台运作时是否由系统自己选择最佳网络连接配置 后台时建议开启discretionary 会话NSURLSession: 获取对象方法: 1.使用共享的会话,该会话使用全局的Cache,Cookie和证书 +(NSURLSession *)sharedSession; 2.创建对应配置的新会话 +(NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration; 3.创建对应配置的新会话,指定会话的委托与委托所处队列,委托将被会话持有,可调会话的invalidateAndCancel关闭会话或调会话finishTasksAndInvalidate等待当前Task结束后关闭,凡是关闭会话委托都将收到URLSession:didBecomeInvalidWithError:回调,收到该回调时会话不再持有该委托 +(NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration delegate:(id<NSURLSessionDelegate>)delegate delegateQueue:(NSOperationQueue *)queue; 任务类型NSURLSessionTask(抽象类)3种子类: 1.获取数据(JSON,XML)任务类型:NSURLSessionDataTask 获取对象方法: 1.不指定完成任务后的block回调块 1.通过传入NSURLRequest对象 -(NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request; 2.通过传入NSURL对象创建 -(NSURLSessionDataTask *)dataTaskWithURL:(NSURL *)url; 2.指定完成任务后的block回调块 1.通过传入NSURLRequest对象 -(NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request completionHandler:(void (^)(NSData *data, NSURLResponse *response, NSError *error))completionHandler; 2.通过传入NSURL对象创建 -(NSURLSessionDataTask *)dataTaskWithURL:(NSURL *)url completionHandler:(void (^)(NSData *data, NSURLResponse *response, NSError *error))completionHandler; 2.上传任务类型:NSURLSessionUploadTask 获取对象方法: 1.不指定完成任务后的block回调块 1.通过指定上传的文件源以及传入NSURLRequest对象 -(NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromFile:(NSURL *)fileURL; 2.通过指定上传的数据源以及传入NSURLRequest对象 -(NSURLSessionDataTask *)dataTaskWithURL:(NSURL *)url; 2.指定完成任务后的block回调块 1.通过指定上传的文件源以及传入NSURLRequest对象 -(NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromFile:(NSURL *)fileURL completionHandler:(void (^)(NSData *data, NSURLResponse *response, NSError *error))completionHandler; 2.通过指定上传的数据源以及传入NSURLRequest对象 -(NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromData:(NSData *)bodyData completionHandler:(void (^)(NSData *data, NSURLResponse *response, NSError *error))completionHandler; 3.下载任务类型(支持断点续下):NSURLSessionDownloadTask 获取对象方法: 1.通过传入NSURLRequest对象以及指定下载完成block回调 -(NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request completionHandler:(void (^)(NSURL *location, NSURLResponse *response, NSError *error))completionHandler; 2.通过传入NSURL对象以及指定下载完成block回调 -(NSURLSessionDownloadTask *)downloadTaskWithURL:(NSURL *)url completionHandler:(void (^)(NSURL *location, NSURLResponse *response, NSError *error))completionHandler; 3.通过之前已经下载的数据以及指定下载完成block回调来创建下载任务 -(NSURLSessionDownloadTask *)downloadTaskWithResumeData:(NSData *)resumeData completionHandler:(void (^)(NSURL *location, NSURLResponse *response, NSError *error))completionHandler; 取消下载范例: -(void)cancelDownload{ if(myDownLoadTask){ [myDownLoadTask cancel];//直接调用cancel方法取消下载,下次下载将重新开始下载 myDownLoadTask=nil; }else{ [myDownLoadTask2 cancelByProducingResumeData:^(NSData *resumeData){//调用该方法取消下载,可以把已经下载的数据缓存起来,用作下次重新下载时直接从已下载数据位置开始下载 hadDownLoadData=resumeData; myDownLoadTask2=nil; }]; } } 恢复下载范例: -(void)resumDownload{ if(!myDownLoadTask2){ if(hadDownLoadData){//该hadDownLoadData为上次取消下载保留出来的已下载数据用户恢复下载使用 myDownLoadTask2=[mySession downloadTaskWithResumeData:hadDownLoadData];//该方式恢复下载不用调resume方法启动,并且在恢复下载时,会回调NSURLSessionDownloadDelegate中的-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes方法,从fileOffset位移处恢复下载任务 }else{ NSString *url=@"http://url/for/image"; NSURLRequest *request=[NSURLRequest requestWithURL:[NSURL URLWithString:url]]; myDownLoadTask=[mySession downloadTaskWithRequest:request]; [myDownLoadTask resume]; } } } 协议2种: 1.NSURLSessionDelegate 2.NSURLSessionTaskDelegate 作用: 1.身份验证 2.完成任务后的动作 3.错误处理 4.下载进度 5.后台任务完成 等 如 处理后台任务的一个委托方法: -(void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session 结合ApplicationDelegate使用: -(void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler 结合使用流程: 1.将任务切换到后台后,session的delegate不会再回调,当所有task完成后,程序被唤醒,并调用ApplicationDelegate的application:handleEventsForBackgroundURLSession:completionHandler:回调 2.在该回调中需要为后台session(由background session的identifier标识)使用成员变量持有指定对应的block回调代码块供后面使用 3.对于每一个完成的后台Task调用该Session的Delegate中的URLSession:downloadTask:didFinishDownloadingToURL:(成功的话)和URLSession:task:didCompleteWithError:(成功或者失败都会调用)方法做处理,拿到以上的block回调代码块可以在这里调用。 后台下载使用范例: -(NSURLSession *)backgroundSession{//懒加载 static NSURLSession *backgroundSession = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ NSURLSessionConfiguration *config = [NSURLSessionConfiguration backgroundSessionConfiguration:@"com.shinobicontrols.BackgroundDownload.BackgroundSession"];//为该后台进程指定一个标识符,在有多个后台下载任务时这个标识符就起作用了。 backgroundSession = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil]; }); return backgroundSession; } -(void)startDownload{ NSString *url=@"http://url/for/image"; NSURLRequest *request=[NSURLRequest requestWithURL:[NSURL URLWithString:url]]; myBackgroundTask=[backgroundSession downloadTaskWithRequest:request]; [myBackgroundTask resume]; } -(void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler{ self.backgroundURLSessionCompletionHandler = completionHandler; } -(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location{ if (session == myBackgroundTask){ myBackgroundTask = nil; if([[UIApplication sharedApplication] delegate].backgroundURLSessionCompletionHandler){ void(^handler)()=[[UIApplication sharedApplication] delegate].backgroundURLSessionCompletionHandler; [[UIApplication sharedApplication] delegate].backgroundURLSessionCompletionHandler=nil; handler(); } } } 下载完成调用以及使用范例: -(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location{ NSFileManager *fileManager=[NSFileManager defaultManager]; NSArray *URLs=[fileManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask]; NSURL *documentsDirectory=URLs[0]; NSURL *destinationPath=[documentsDirectory URLByAppendingPathComponent:[location lastPathComponent]]; NSError *error; [fileManager removeItemAtURL:destinationPath error:NULL]; BOOL success=[fileManager copyItemAtURL:location toURL:destinationPath error:&error]; if(success){ dispatch_async(dispatch_get_main_queue(),^{ UIImage *image=[UIImage imageWithContentsOfFile:[destinationPath path]]; self.imageView.image=image; self.imageView.contentMode=UIViewContentModeScaleAspectFill; self.imageView.hidden=No; }); else{ NSLog(@"Couldn`t copy the downloaded file"); } if(downloadTask==myTask){ myTask=nil; } } } 下载结束(成功与否)回调的方法: -(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error{ if(error){ NSLog(@"下载失败"); }else{ NSLog(@"下载成功"); } dispatch_async(dispatch_get_main_queue(),^{ self.progressIndicator.hidden=YES; }); } 当调用NSURLSessionTask的cancel对象方法取消下载时,最后也会回调该方法 下载进度获取(会多次回调)的代理方法: /* bytesWritten:每次写入的data字节数 totalBytesWritten:当前一共写入的data字节数 totalBytesExpectedToWrite:期望守到的所有data字节数 */ -(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten BytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite{ double currentProgress = totalBytesWritten / (double)totalBytesExpectedToWrite; dispatch_async(dispatch_get_main_queue(), ^{ self.progressIndicator.hidden = NO; self.progressIndicator.progress = currentProgress; }); }HTTPS请求处理,证书作用以及使用: