People Lack Willpower挺据,Rather Than Strength炫刷!
客戶端和服務(wù)器之間如何通信?
-
簡而言之:
- 客戶端和服務(wù)器之間通信,由于使用不同語言編程,所以使用HTTP協(xié)議,完成雙方數(shù)據(jù)交流;客戶端以HTTP方式發(fā)送請求,服務(wù)器做出響應(yīng);
-
常見請求發(fā)送方式:
- NSURLConnection;
- NSURLSession;
- AFNetworking;
-
發(fā)送請求步驟:
// NSURLConnection: 1.創(chuàng)建url; 2.根據(jù)url創(chuàng)建request; 3.使用NSURLConnection發(fā)送request;
HTTP
- HTTP協(xié)議中向服務(wù)器發(fā)送請求的方法有多種,我們開發(fā)中常用的有g(shù)et/post;
- 1.get:處理純粹獲得資源的請求,同時,參數(shù)不能太大,不超過1KB;
- 2.post:處理需要保密(簡單保密),參數(shù)較大的請求
NSURLConnection
-
發(fā)送請求步驟:
// NSURLConnection: 1.創(chuàng)建url; 2.根據(jù)url創(chuàng)建request; 3.使用NSURLConnection發(fā)送request;
?
-
發(fā)送請求方式:
- NSURLConnection中提供發(fā)送request的方案:
1.sendSync....:主線程中進(jìn)行,比較耗時,會阻塞; 2.sendAsync...:在子線程中進(jìn)行,可惜不能監(jiān)控服務(wù)器返回的響應(yīng)體中的data進(jìn)度 3.initWithRequest.....可以做到...監(jiān)控進(jìn)度,且是子線程. 或者:connectionWithRequest....
?
- NSURLRequest
- 用于保存請求地址/請求頭/請求體
- 默認(rèn)情況下NSURLRequest會自動給我們設(shè)置好請求頭
- request默認(rèn)情況下就是GET請求
登錄請求
- get方法-------NSURLRequest同步/異步方法發(fā)送請求:
/*=======================get同步方法發(fā)送request================================*/
- (void)sendSync
{
// NSURLConnection-->http采用get請求|sendSync...方案發(fā)送請求
// 1.創(chuàng)建URL
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login?username=520it&pwd=520it&type=JSON"];
// 2.創(chuàng)建request
// 默認(rèn)情況下NSURLRequest會自動給我們設(shè)置好請求頭
// request默認(rèn)情況下就是GET請求
NSURLRequest *request = [NSURLRequest requestWithURL:url];
// 3.發(fā)送request
/*
第一個參數(shù):需要請求的對象;
第二個參數(shù):服務(wù)返回給我們的響應(yīng)頭信息;
第三個參數(shù):錯誤信息;
返回值:服務(wù)器返回給我們的響應(yīng)體
*/
// NSURLResponse *response = nil;
// response的真實(shí)類型是:
NSHTTPURLResponse *response = nil;
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:nil];
// 打印響應(yīng)頭/體信息
NSLog(@"%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
NSLog(@"%@",response.allHeaderFields);
NSLog(@"touches...即將結(jié)束-------");
/*
2015-09-07 09:19:32.287 01-NSURLConnection基本使用[1116:143990] {"success":"登錄成功"}
2015-09-07 09:19:32.287 01-NSURLConnection基本使用[1116:143990] {
"Content-Type" = "application/json;charset=UTF-8";
Date = "Mon, 07 Sep 2015 01:19:29 GMT";
Server = "Apache-Coyote/1.1";
"Transfer-Encoding" = Identity;
}
2015-09-07 09:19:32.287 01-NSURLConnection基本使用[1116:143990] touches...即將結(jié)束-----
*/
}
?
/*============================get 異步方法發(fā)送request======================*/
- (void)sendAsync
{
// 異步方法發(fā)送request
// 1.創(chuàng)建URL
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login?username=520it&pwd=520it&type=JSON"];
// 2.創(chuàng)建request
NSURLRequest *request = [NSURLRequest requestWithURL:url];
// 3.異步發(fā)送request
/*
參數(shù)說明:
參數(shù)一:需要請求的對象;
參數(shù)二:回調(diào)block的隊(duì)列,決定了block在哪個線程中執(zhí)行;
參數(shù)三:回調(diào)block(響應(yīng)體句柄)
*/
// 注意:如果這里是同步,會阻塞當(dāng)前線程
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
/*
response:響應(yīng)頭;
data:響應(yīng)體;
connectionError:錯誤信息;
*/
NSLog(@"%@",request.HTTPBody);
NSLog(@"%@",request.allHTTPHeaderFields);
/*
2015-09-07 09:59:20.422 01-NSURLConnection基本使用[1425:362793] (null)
2015-09-07 09:59:20.423 01-NSURLConnection基本使用[1425:362793] (null)
為啥是NULL????
*/
NSLog(@"%@",response);
NSLog(@"%@",[NSThread currentThread]);
NSLog(@"%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
}];
NSLog(@"touches...即將結(jié)束-------");
/*
2015-09-07 09:15:42.689 01-NSURLConnection基本使用[1075:121037] touches...即將結(jié)束-------
2015-09-07 09:15:42.731 01-NSURLConnection基本使用[1075:121037] <NSThread: 0x7fd649d19e20>{number = 1, name = main}
2015-09-07 09:15:42.731 01-NSURLConnection基本使用[1075:121037] {"success":"登錄成功"}
*/
}
-
登錄請求:請求頭/體
登錄請求.png -
post方法發(fā)送請求,這里以異步為例:
// POST方法:可監(jiān)控數(shù)據(jù)接收進(jìn)度 // 1.創(chuàng)建URL NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login"]; // 2.創(chuàng)建request-->請求需要是可變類型 NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; // 設(shè)置請求方式 request.HTTPMethod = @"POST"; // 這里一定要大寫 // httpbody:NSData類型 // 注意: 如果是給POST請求傳遞參數(shù): 那么不需要寫?號,?只是get方法中參數(shù)與地址的分隔符! request.HTTPBody = [@"username=520it&pwd=520it&type=JSON" dataUsingEncoding:NSUTF8StringEncoding]; // 3.發(fā)送請求 [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) { NSLog(@"%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]); }];
-
中文問題
- 說明:
默認(rèn)情況下,get方法,需要轉(zhuǎn)碼;
-
默認(rèn)情況下,post方法,不需要轉(zhuǎn)碼,因?yàn)閰?shù)放在請求體中,而且是以二進(jìn)制形式:
request.HTTPBody = [@"username=520it&pwd=520it&type=JSON" dataUsingEncoding:NSUTF8StringEncoding];
-
開發(fā)中,考慮可能出錯,一律轉(zhuǎn)碼.
// get方法中的中文轉(zhuǎn)碼: - (void)get_sendAsync { // 請求中的中文問題 // get方法--->要先轉(zhuǎn)碼?? // 1.url NSString *urlStr = @"http://120.25.226.186:32812/login2?username=小碼哥&pwd=520it&type=JSON"; // 轉(zhuǎn)碼前 NSLog(@"轉(zhuǎn)碼前---%@",urlStr); urlStr = [urlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; NSLog(@"轉(zhuǎn)碼后---%@",urlStr); NSURL *url = [NSURL URLWithString:urlStr]; // 2.request NSURLRequest *request = [NSURLRequest requestWithURL:url]; // 3.sendAsync [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) { NSLog(@"%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]); }]; /* 可見:get方法發(fā)送請求時,參數(shù)中不能有中文,需要轉(zhuǎn)碼 2015-09-07 11:41:06.128 03-URL中文問題[2576:823835] 轉(zhuǎn)碼前---http://120.25.226.186:32812/login2?username=小碼哥&pwd=520it&type=JSON 2015-09-07 11:41:06.128 03-URL中文問題[2576:823835] 轉(zhuǎn)碼后---http://120.25.226.186:32812/login2?username=%E5%B0%8F%E7%A0%81%E5%93%A5&pwd=520it&type=JSON 2015-09-07 11:41:06.201 03-URL中文問題[2576:823835] {"success":"登錄成功"} */ } //======================================================= // post方法--->無需轉(zhuǎn)碼?? // 實(shí)際開發(fā)中,無論get/post都進(jìn)行轉(zhuǎn)碼,省的更改. // 1.url NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login2"]; // 2.request NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; request.HTTPMethod = @"POST"; // 這里將參數(shù)轉(zhuǎn)換為二進(jìn)制data,無需再轉(zhuǎn)碼!?? request.HTTPBody = [@"username=小碼哥&pwd=520it&type=JSON" dataUsingEncoding:NSUTF8StringEncoding]; // type可以不寫 // 3.sendAsync [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) { NSLog(@"%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]); }];
?
- 說明:
下載請求
-
說明:
- 由于我們需要對下載過程進(jìn)行監(jiān)控,所以這里我們需要對NSURLConnection對象設(shè)置代理!
-
下載請求步驟:
- 1.url創(chuàng)建;
- 2.request創(chuàng)建;
- 3.創(chuàng)建connection,設(shè)置代理,執(zhí)行request;
- 4.實(shí)現(xiàn)代理方法;
-
示例:
-
1.request
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { // 通過initWithRequest.../connection方法發(fā)送請求,可以監(jiān)控數(shù)據(jù)下載進(jìn)度 // 1.URL創(chuàng)建---->下載請求?? NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/images/minion_02.png"]; // 2.request創(chuàng)建 NSURLRequest *request = [NSURLRequest requestWithURL:url]; // 3.發(fā)送請求 // NSURLConnection *connect = [[NSURLConnection alloc] initWithRequest:request delegate:self]; // [NSURLConnection connectionWithRequest:request delegate:self]; NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO]; // 如果startImmediately:NO,則需要手動開啟發(fā)動請求 [connection start]; // NSLog(@"%@",connect); /* <NSURLConnection: 0x7f83c0716c70> { request: <NSURLRequest: 0x7f83c0745600> { URL: http://120.25.226.186:32812/resources/images/minion_02.png } } // 可見這里不是我們想要下載的東西,可以不寫 */ }
-
2.代理方法
// --------------------------------代理方法---------------------------- #pragma mark - NSURLConnectionDataDelegate // 只要接收到服務(wù)器的響應(yīng)就會調(diào)用 // response:響應(yīng)頭 - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { // NSLog(@"%s", func); // 在此處,我們可以獲得服務(wù)器返回給我們的文件總大小 self.totalLength = response.expectedContentLength; // response中包含的屬性含義: // 收到數(shù)據(jù)建議名字 NSLog(@"%@",response.suggestedFilename); // 服務(wù)器響應(yīng)數(shù)據(jù)大小 NSLog(@"%lld",response.expectedContentLength); // 請求url NSLog(@"%@",response.URL); // 數(shù)據(jù)類型 NSLog(@"%@",response.MIMEType); // 2015-09-07 11:06:40.240 02-NSURLConnection其他用法[2140:690910] minion_02.png // 2015-09-07 11:06:40.241 02-NSURLConnection其他用法[2140:690910] 43852 // 2015-09-07 11:06:40.241 02-NSURLConnection其他用法[2140:690910] http://120.25.226.186:32812/resources/images/minion_02.png // 2015-09-07 11:06:40.241 02-NSURLConnection其他用法[2140:690910] image/png NSLog(@"%@",response); // 可見此處response包含兩大部分內(nèi)容:1.請求url;2.響應(yīng)頭; // 2015-09-07 10:59:48.113 02-NSURLConnection其他用法[1975:661374] <NSHTTPURLResponse: 0x7feadb7d5940> { URL: http://120.25.226.186:32812/resources/images/minion_02.png } { status code: 200, headers { // "Accept-Ranges" = bytes; // "Content-Length" = 43852; // "Content-Type" = "image/png"; // Date = "Mon, 07 Sep 2015 02:42:51 GMT"; // Etag = "W/\"43852-1409456092000\""; // "Last-Modified" = "Sun, 31 Aug 2014 03:34:52 GMT"; // Server = "Apache-Coyote/1.1"; // } } } // 接收到服務(wù)器返回的數(shù)據(jù)時調(diào)用(該方法可能調(diào)用一次,或者多次) // data:服務(wù)器返回的數(shù)據(jù)(是當(dāng)前一次返回的,不是累積量) - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { // NSLog(@"%s", func); self.currentLength += data.length; NSLog(@"%f",1.0 * self.currentLength / self.totalLength); } // 數(shù)據(jù)下載完成時調(diào)用 - (void)connectionDidFinishLoading:(NSURLConnection *)connection { // NSLog(@"%s", func); self.currentLength = 0; } // 請求錯誤時調(diào)用(請求超時) /* connection:didFailWithError: will be called at most once, if an error occurs during a resource load. No other callbacks will be made after.<p> */ - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { // NSLog(@"%s", func); } /* 可見:服務(wù)器響應(yīng):響應(yīng)頭--->響應(yīng)體-->下載完成 2015-09-07 10:57:22.590 02-NSURLConnection其他用法[1939:649504] -[ViewController connection:didReceiveResponse:] 2015-09-07 10:57:22.591 02-NSURLConnection其他用法[1939:649504] -[ViewController connection:didReceiveData:] 2015-09-07 10:57:22.591 02-NSURLConnection其他用法[1939:649504] -[ViewController connectionDidFinishLoading:] */
-