現在的移動開發必然涉及到伺服器,那就不能不說網絡。在網絡程式設計中,有幾個基本的概念:
- 用戶端(Client): 移動應用 (iOS, Android等應用)
- 伺服器(Server): 為用戶端提供服務、提供資料、提供資源的機器
- 請求(Request): 用戶端向伺服器索取資料的一種行為
- 響應(Response): 伺服器對用戶端的請求作出響應,一般指傳回資料給用戶端
圖解:
用戶端是如何找到伺服器呢,主要是通過URL找到想要連接配接的伺服器,而什麼是URL?
- URL的全稱是 Uniform Resource Locator (統一起源定位符)
- 通過1個URL,能找到網際網路上唯一的一個資源
- URL就是資源的位址,位置,網際網路上的每一個資源都有唯一的URL
- URL的基本格式 = 協定://主機位址/路徑(http://www.baidu.com/img/logo.png)
協定: 不同的協定,代表着不同的資源查找方式,資源傳輸方式
主機位址: 存放資源的主機(伺服器)的IP位址(域名)
路徑: 資源在主機(伺服器)中的具體位置
HTTP協定的特點:
- 簡單快速
因為http協定簡單,是以Http伺服器的程式規模小,因而通信速度很快
- 靈活
Http允許各種各樣的資料
Http協定規定: 一個完整的由用戶端和伺服器端的Http請求包括以下内容:
iOS中發送Http的請求方案:
- 蘋果原生:NSURLConnection(比較古老,不推薦使用), NSURLSession(推薦使用)
- 第三方架構: AFNetworking
NSURLConnection的GET
- 常用類
- NSURL:請求位址
- NSURLRequest:一個NSURLRequest對象就代表一個請求,它包含的資訊有(一個NSURL對象, 請求方法、請求頭、請求體,請求逾時......)
- NSMutableURLRequest:NSURLRequest的子類
- NSURLConnection (負責發送請求,建立用戶端和伺服器的連接配接發送資料給伺服器,并收集來自伺服器的響應資料)
2. NSURLConnection的使用步驟
- 建立一個NSURL對象,設定請求路徑
- 傳入NSURL建立一個NSURLRequest對象,設定請求頭和請求體
- 使用NSURLConnection發送請求
3. 發送同步請求: 主要使用+ (NSData *)sendSynchronousRequest:(NSURLRequest *)request returningResponse:(NSURLResponse **)response error:(NSError **)error;方法
/*
GET:http://120.25.226.186:32812/login?username=123&pwd=456&type=JSON
協定+主機位址+接口名稱+?+參數1&參數2&參數3
post:http://120.25.226.186:32812/login
協定+主機位址+接口名稱
*/
//GET,沒有請求體
//1.确定請求路徑
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login?username=520it&pwd=520it&type=JSON"];
//2.建立請求對象
//請求頭不需要設定(預設的請求頭)
//請求方法--->預設為GET
NSURLRequest *request = [[NSURLRequest alloc]initWithURL:url];
//3.發送請求
//真實類型:NSHTTPURLResponse
NSHTTPURLResponse *response = nil;
/*
第一個參數:請求對象
第二個參數:響應頭資訊
第三個參數:錯誤資訊
傳回值:響應體
*/
//該方法是阻塞的,即如果該方法沒有執行完則後面的代碼将得不到執行
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:nil];
//4.解析 data--->字元串
//NSUTF8StringEncoding
NSLog(@"%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);
NSLog(@"%zd",response.statusCode);
4. 發送異步請求: 主要使用兩類方法
- Block方法
+ (void)sendAsynchronousRequest:(NSURLRequest*) request queue:(NSOperationQueue*) queue completionHandler:(void (^)(NSURLResponse* response, NSData* data, NSError* connectionError)) handler;
//1.确定請求路徑
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login?username=520it&pwd=520it&type=JSON"];
//2.建立請求對象
//請求頭不需要設定(預設的請求頭)
NSURLRequest *request = [[NSURLRequest alloc]initWithURL:url];
//3.發送異步請求
/*
第一個參數:請求對象
第二個參數:隊列 決定代碼塊completionHandler的調用線程
第三個參數:completionHandler 當請求完成(成功|失敗)的時候回調
response:響應頭
data:響應體
connectionError:錯誤資訊
*/
[NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc]init] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
//4.解析資料
NSLog(@"%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);
NSHTTPURLResponse *res = (NSHTTPURLResponse *)response;
NSLog(@"%zd",res.statusCode);
NSLog(@"%@",[NSThread currentThread]);
}];
- 代理方法
- (id)initWithRequest:(NSURLRequest *)request delegate:(id)delegate;
+ (NSURLConnection*)connectionWithRequest:(NSURLRequest *)request delegate:(id)delegate;
- (id)initWithRequest:(NSURLRequest *)request delegate:(id)delegate startImmediately:(BOOL)startImmediately;
在startImmediately = NO的情況下,需要調用start方法開始發送請
- (void)start;
成為NSURLConnection的代理,最好遵守NSURLConnectionDataDelegate協定
5. NSURLConnectionDataDelegate協定中的代理方法
- 開始接收到伺服器的響應時調用
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response;
- 接收到伺服器傳回的資料時調用(伺服器傳回的資料比較大時會調用多次)
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data;
- 伺服器傳回的資料完全接收完畢後調用
- (void)connectionDidFinishLoading:(NSURLConnection *)connection;
- 請求出錯時調用(比如請求逾時)
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error;
-(void)delegate
{
//1.确定請求路徑
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login?username=123&pwd=123&type=JSON"];
//2.建立請求對象
NSURLRequest *request = [NSURLRequest requestWithURL:url];
//3.設定代理,發送請求
//3.1
//[NSURLConnection connectionWithRequest:request delegate:self];
//3.2
//[[NSURLConnection alloc]initWithRequest:request delegate:self];
//3.3 設定代理,時候發送請求需要檢查startImmediately的值
//(startImmediately == YES 會發送 | startImmediately == NO 則需要調用start方法)
NSURLConnection * connect = [[NSURLConnection alloc]initWithRequest:request delegate:self startImmediately:NO];
//調用開始方法
[connect start];
// [connect cancel];//取消
}
#pragma mark ----------------------
#pragma mark NSURLConnectionDataDelegate
//1.當接收到伺服器響應的時候調用
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
NSLog(@"%s",__func__);
}
//2.接收到伺服器傳回資料的時候調用,調用多次
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
NSLog(@"%s",__func__);
//拼接資料
[self.resultData appendData:data];
}
//3.當請求失敗的時候調用
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(@"%s",__func__);
}
//4.請求結束的時候調用
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(@"%s",__func__);
NSLog(@"%@",[[NSString alloc]initWithData:self.resultData encoding:NSUTF8StringEncoding]);
}
NSURLConnection的POST
1. 常用類與GET類似
2. 比較特殊的處理方法
NSMutableURLRequest是NSURLRequest的子類,常用方法有
- 設定請求逾時等待時間(超過這個時間就算逾時,請求失敗)
- (void)setTimeoutInterval:(NSTimeInterval)seconds;
- 設定請求方法(比如GET和POST)
- (void)setHTTPMethod:(NSString *)method;
- 設定請求體
- (void)setHTTPBody:(NSData *)data;
- 設定請求頭
- (void)setValue:(NSString *)value forHTTPHeaderField:(NSString *)field;
-(void)post
{
//1.确定請求路徑
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login"];
//2.建立可變請求對象
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
//3.修改請求方法,POST必須大寫
request.HTTPMethod = @"POST";
//設定屬性,請求逾時(超過這個時間算請求失敗)
request.timeoutInterval = 10;
//設定請求頭User-Agent
//注意:key一定要一緻(用于傳遞資料給背景)
[request setValue:@"ios 10.1" forHTTPHeaderField:@"User-Agent"];
//4.設定請求體資訊,字元串--->NSData
request.HTTPBody = [@"username=520it&pwd=123&type=JSON" dataUsingEncoding:NSUTF8StringEncoding];
//5.發送請求
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
//6.解析資料,NSData --->NSString
NSLog(@"%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);
}];
}
代理方法與上面block類似,除了添加request.HTTPMethod和request.HTTPBody等其餘與GET的代理一樣。
NSURLConnection小檔案下載下傳
#import "ViewController.h"
@interface ViewController ()<NSURLConnectionDataDelegate>
/** 注釋 */
@property (nonatomic, strong) NSMutableData *fileData;
@property (nonatomic, assign) NSInteger totalSize;
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@end
@implementation ViewController
-(NSMutableData *)fileData
{
if (_fileData == nil) {
_fileData = [NSMutableData data];
}
return _fileData;
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
[self download3];
}
//耗時操作[NSData dataWithContentsOfURL:url]
-(void)download1
{
//1.url
NSURL *url = [NSURL URLWithString:@"http://img5.imgtn.bdimg.com/it/u=1915764121,2488815998&fm=21&gp=0.jpg"];
//2.下載下傳二進制資料
NSData *data = [NSData dataWithContentsOfURL:url];
//3.轉換
UIImage *image = [UIImage imageWithData:data];
}
//1.無法監聽進度
//2.記憶體飙升
-(void)download2
{
//1.url
// NSURL *url = [NSURL URLWithString:@"http://imgsrc.baidu.com/forum/w%3D580/sign=54a8cc6f728b4710ce2ffdc4f3cec3b2/d143ad4bd11373f06c0b5bd1a40f4bfbfbed0443.jpg"];
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/videos/minion_01.mp4"];
//2.建立請求對象
NSURLRequest *request = [NSURLRequest requestWithURL:url];
//3.發送請求
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
//4.轉換
// UIImage *image = [UIImage imageWithData:data];
//
// self.imageView.image = image;
//NSLog(@"%@",connectionError);
//4.寫資料到沙盒中
NSString *fullPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject]stringByAppendingPathComponent:@"123.mp4"];
[data writeToFile:fullPath atomically:YES];
}];
}
//記憶體飙升
-(void)download3
{
//1.url
// NSURL *url = [NSURL URLWithString:@"http://imgsrc.baidu.com/forum/w%3D580/sign=54a8cc6f728b4710ce2ffdc4f3cec3b2/d143ad4bd11373f06c0b5bd1a40f4bfbfbed0443.jpg"];
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/videos/minion_01.mp4"];
//2.建立請求對象
NSURLRequest *request = [NSURLRequest requestWithURL:url];
//3.發送請求
[[NSURLConnection alloc]initWithRequest:request delegate:self];
}
#pragma mark ----------------------
#pragma mark NSURLConnectionDataDelegate
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
NSLog(@"didReceiveResponse");
//得到檔案的總大小(本次請求的檔案資料的總大小)
self.totalSize = response.expectedContentLength;
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
// NSLog(@"%zd",data.length);
[self.fileData appendData:data];
//進度=已經下載下傳/檔案的總大小
NSLog(@"%f",1.0 * self.fileData.length /self.totalSize);
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(@"connectionDidFinishLoading");
//4.寫資料到沙盒中
NSString *fullPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject]stringByAppendingPathComponent:@"123.mp4"];
[self.fileData writeToFile:fullPath atomically:YES];
NSLog(@"%@",fullPath);
}
@end