网络通讯

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请求处理,证书作用以及使用:

 

posted @ 2016-03-13 13:44  Jk_Chan  阅读(328)  评论(0编辑  收藏  举报