HTTP协议(二)之HTTP请求
一、HTTP请求的方法
在HTTP/1.1协议中,定义了8种发送HTTP请求的方法,有GET、POST、OPTION、HEAD、PUT、DELETE、TRACE、CONNECT、PACH。根据HTTP协议的解释,不同的方法对资源有不同的操作方式:
1、PUT:增
2、DELETE:删
3、POST:改
4、GET:查
其中最常用的时GET和POST。GET和POST的主要区别在数据的传递上。
1、GET
在URL后面以?的形式跟上发给服务器的参数,多个参数之间用&隔开,比如:
http://localhost:8080/MJServer/login?username=name&pwd=123
由于浏览器和服务器对URL的长度限制,因此在URL后面附带的参数是有限制的,通常不超过1KB。
2、POST
POST发给服务器的参数都放在请求体中,理论上POST传递的数据大小是没有限制的。
3、如何选择
如果要传递大量数据,比如文件上传,只能用POST请求。安全性来说,GET要比POST差些,如果包含一些敏感的信息建议用POST,如果仅仅是从服务器获取数据,例如查询一些信息,建议使用GET,如果是增加、修改和删除数据,建议用POST。
二、iOS中发送HTTP请求的方案
苹果原生的解决方案有:
1、NSURLConnection --用法比较简单的直接的一种方案。
2、NSURLSession --iOS 7新出的技术,比上一种方案功能更强大
3、CFNetwork --底层的解决方案,纯C语言
第三方框架,比较常用的有:
1、ASIHttpRequest:功能强大,但是已经停止更新
2、AFNetworking:简单易用,提供了基本够用的功能。
为了提高开发效率,建议使用第三方框架。
1、NSURLConnection
1、常用类:
NSURL:请求地址
NSURLRequest:封装一个请求,保存发给服务器的全部数据,包含一个NSURL对象、请求行、请求头、请求体等。
NSMutableURLRequest:NSURLRequest的子类
NSURLConnection:建立客户端和服务器的连接,发送NSURLRequest的数据给服务器,并接收来自服务器的响应数据。
2、NSURLConnection的使用
先看一段获取天气情况的代码:
/** * 获取天气信息---异步block */ - (void)getWeatherInfo0 { //显示一个加载框 MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:[UIApplication sharedApplication].windows.lastObject animated:YES]; hud.labelText = @"正在加载"; hud.dimBackground = YES; hud.removeFromSuperViewOnHide = YES; //发送HTTP请求 NSString *str = @"http://www.weather.com.cn/adat/sk/101010100.html"; NSURL *url = [NSURL URLWithString:str]; NSURLRequest *request = [NSURLRequest requestWithURL:url]; [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) { //对返回的数据进行处理,例如json解析 NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil]; NSDictionary *weatherinfoDict = [dict objectForKey:@"weatherinfo"]; [self weatherInfoHandler:weatherinfoDict]; [hud hide:YES]; }]; } /** * 处理获取的天气信息 * * @param weatherinfoDict 天气信息 */ - (void)weatherInfoHandler:(NSDictionary *)weatherinfoDict { //解析获取的内容 //city NSString *city = [weatherinfoDict objectForKey:@"city"]; UILabel *cityLabel = [[UILabel alloc] init]; cityLabel.text = [NSString stringWithFormat:@"城市:%@", city]; cityLabel.frame = CGRectMake(110, 90, 100, 25); [self.view addSubview:cityLabel]; //发布时间 NSString *time = [weatherinfoDict objectForKey:@"time"]; UILabel *timeLabel = [[UILabel alloc] init]; timeLabel.text = [NSString stringWithFormat:@"发布时间:%@", time]; timeLabel.frame = CGRectMake(110, 120, 130, 25); [self.view addSubview:timeLabel]; //风向 NSString *wd = [weatherinfoDict objectForKey:@"WD"]; UILabel *wdLabel = [[UILabel alloc] init]; wdLabel.text = [NSString stringWithFormat:@"风向:%@", wd]; wdLabel.frame = CGRectMake(110, 150, 100, 25); [self.view addSubview:wdLabel]; //风级 NSString *ws = [weatherinfoDict objectForKey:@"WS"]; UILabel *wsLabel = [[UILabel alloc] init]; wsLabel.text = [NSString stringWithFormat:@"风级:%@", ws]; wsLabel.frame = CGRectMake(110, 180, 100, 25); [self.view addSubview:wsLabel]; }
首先使用一个获取天气的地址创建一个NSURL对象,设置请求路径;然后使用NSURL创建一个NSURLRequest对象,设置请求头和请求体,最后使用NSURLConnection发送NSURLRequest。
最后显示结果:
NSURLConnection发送请求的方法有以下几种:
1、异步请求,异步请求根据数据处理的方式可分为2种:
a、block回调方式
+ (void)sendAsynchronousRequest:(NSURLRequest*) request queue:(NSOperationQueue*) queue completionHandler:(void (^)(NSURLResponse* response, NSData* data, NSError* connectionError)) handler NS_AVAILABLE(10_7, 5_0);
request是构造的NSURLRequest请求,queue是后面的block处理所在的线程,completionHandler是处理获取的数据所在的block。
b、代理方式
/* Designated initializer */ - (id)initWithRequest:(NSURLRequest *)request delegate:(id)delegate startImmediately:(BOOL)startImmediately NS_AVAILABLE(10_5, 2_0); - (id)initWithRequest:(NSURLRequest *)request delegate:(id)delegate; + (NSURLConnection*)connectionWithRequest:(NSURLRequest *)request delegate:(id)delegate;
在这种情况下,需要调用start方法开始发送请求
- (void)start NS_AVAILABLE(10_5, 2_0);
成为NSURLConnection的代理,根据需要选择遵守相应的代理
1. NSURLConnectionDelegate 2. NSURLConnectionDataDelegate 3. NSURLConnectionDownloadDelegate
下面是使用代理处理方式发送请求的代码:
/** * 获取天气信息---异步代理方式 */ - (void)getWeatherInfo1 { //发送HTTP请求 NSString *str = @"http://www.weather.com.cn/adat/sk/101010100.html"; NSURL *url = [NSURL URLWithString:str]; NSURLRequest *request = [NSURLRequest requestWithURL:url]; NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO]; [connection start]; } #pragma mark 代理回调 - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil]; if (dict) { NSDictionary *weatherinfoDict = [dict objectForKey:@"weatherinfo"]; [self weatherInfoHandler:weatherinfoDict]; } }
- (id)initWithRequest:(NSURLRequest *)request delegate:(id)delegate startImmediately:(BOOL)startImmediately NS_AVAILABLE(10_5, 2_0);
这个方法的startImmediately如果为YES的话,表示建立连接后就立即开始下载数据,如果为NO的话需要调用start方法开始下载数据。
2、同步请求
+ (NSData *)sendSynchronousRequest:(NSURLRequest *)request returningResponse:(NSURLResponse **)response error:(NSError **)error;
response是相应信息,有状态行和响应头等响应信息。下面是使用同步请求获取的天气信息:
/** * 获取天气信息---同步请求 */ - (void)getWeatherInfo1 { //发送HTTP请求 NSString *str = @"http://www.weather.com.cn/adat/sk/101010100.html"; NSURL *url = [NSURL URLWithString:str]; NSURLRequest *request = [NSURLRequest requestWithURL:url]; NSURLResponse *response = nil; NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:nil]; NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil]; NSDictionary *weatherinfoDict = [dict objectForKey:@"weatherinfo"]; [self weatherInfoHandler:weatherinfoDict]; // NSLog(@"response %@", [response description]); }
最后的Log输出是:
2015-07-02 15:57:25.102 HttpDemo[1915:607] response { URL: http://www.weather.com.cn/adat/sk/101010100.html } { status code: 200, headers { "Accept-Ranges" = bytes; Age = 176; "CC_CACHE" = "TCP_HIT"; "Cache-Control" = "max-age=1800"; Connection = "keep-alive"; "Content-Encoding" = gzip; "Content-Length" = 181; "Content-Type" = "text/html; charset=utf-8"; Date = "Thu, 02 Jul 2015 07:54:29 GMT"; Expires = "Thu, 02 Jul 2015 08:25:49 GMT"; Server = "Apache/2.2.0"; "Set-Cookie" = "BIGipServerwww_pool=1253639229.20480.0000; path=/"; } }
同步请求会堵塞主线程,一般网络请求常用异步请求。另外,上面HTTP请求的请求方法都是默认的GET方法,如果要更改请求方法和请求体可以使用NSURLRequest的子类NSMutableURLRequest,常用设置有:
- (void)setURL:(NSURL *)URL; //设置请求地址 - (void)setCachePolicy:(NSURLRequestCachePolicy)policy; //设置缓存策略 - (void)setTimeoutInterval:(NSTimeInterval)seconds; //设置超时时间 - (void)setHTTPMethod:(NSString *)method; //设置请求方法 - (void)setAllHTTPHeaderFields:(NSDictionary *)headerFields; //设置请求头部域 - (void)setHTTPBody:(NSData *)data; //设置请求体
最后附上Demo:HTTP协议(二)demo