1.為什么學(xué)習(xí)網(wǎng)絡(luò)?
1.1 學(xué)習(xí)網(wǎng)絡(luò)是學(xué)習(xí)實(shí)時(shí)更新數(shù)據(jù)的手段
1.2 掌握了實(shí)時(shí)更新數(shù)據(jù)的手段,可以使APP變得更加有吸引力
1.3 數(shù)據(jù)的實(shí)時(shí)的更新是在服務(wù)器端發(fā)生的
1.4 客戶端只需要把服務(wù)器最新的數(shù)據(jù)加載到客戶端,然后展示即可
1.5 客戶端的網(wǎng)絡(luò)開發(fā)只做一件事,向服務(wù)器發(fā)送網(wǎng)絡(luò)請求,得到服務(wù)器的"最新"數(shù)據(jù)展示在界面上
1.6 客戶端的開發(fā)者,只需要關(guān)心"請求怎么發(fā),響應(yīng)怎么處理"
2.網(wǎng)絡(luò)核心
2.1 客戶端 : 就是手機(jī) / APP
2.2 服務(wù)器端 : 為客戶端提供數(shù)據(jù)的"特殊"的計(jì)算機(jī)
2.3 請求 : 客戶端向服務(wù)器端獲取數(shù)據(jù)的行為
2.4 響應(yīng) : 服務(wù)器端對客戶端的請求作出的反應(yīng)
3.網(wǎng)絡(luò)開發(fā)的結(jié)構(gòu)
3.1 客戶端 : 發(fā)送請求,告訴服務(wù)器自己要什么數(shù)據(jù)
3.2 服務(wù)器端 : 服務(wù)器得到客戶端的請求之后,就去數(shù)據(jù)庫里面找客戶端需要的數(shù)據(jù),如果找到就把數(shù)據(jù)發(fā)送客戶端
3.3 數(shù)據(jù)庫 : 專門存放數(shù)據(jù)的地方
3.4 實(shí)際開發(fā)中,作為移動(dòng)端開發(fā),只需要關(guān)心客戶端的開發(fā)就可以了
4.服務(wù)器
4.1 測試服務(wù)器 : 在開發(fā)階段使用的服務(wù)器,是本地的,所以數(shù)據(jù)加載比較快,方便前后端開發(fā)者調(diào)節(jié)數(shù)據(jù)
4.2 正式服務(wù)器 : APP發(fā)布上線之后,訪問的服務(wù)器;里面的數(shù)據(jù)都是正確的,可以被任何備用戶訪問
4.3 黑馬學(xué)習(xí)網(wǎng)絡(luò)課程,選擇的是本地apache服務(wù)器,只在學(xué)習(xí)時(shí)使用;實(shí)際開發(fā),使用自己公司的測試和正式服務(wù)器
5.URL
http://open.api.yaolan.com/api/bbs/post?limit=20&start=0&source=ios&tid=53251140&token=3784
5.1 URL的概念 : 統(tǒng)一資源定位符 (數(shù)據(jù)在網(wǎng)絡(luò)中的路徑 / 地址)
5.1.1 通過唯一的URL可以獲取到網(wǎng)絡(luò)中唯一的數(shù)據(jù)
5.1.2 每個(gè)人都有住址.URL就是類似人的住址.
5.2 URL的格式
5.2.1 協(xié)議頭
http:// 表示傳輸任何數(shù)據(jù)
https:// 表示傳輸任何安全數(shù)據(jù)
ftp:// 表示傳輸大文件
tel:// 表示打電話的 (tel://18510000001)
sms:// 表示發(fā)送短信 (sms://18510000001)
mailto:// 表示發(fā)送郵件 (mailto://zhangjiesharp@163.com)
5.2.2 服務(wù)器地址 / 域名 / 服務(wù)器IP
"open.api.yaolan.com" : 表示向哪個(gè)公司的服務(wù)器獲取數(shù)據(jù)
"www.baidu.com" : 表示向百度公司的服務(wù)器獲取數(shù)據(jù)
服務(wù)器地址 服務(wù)器地址 / 域名 / 服務(wù)器IP : 表示這個(gè)計(jì)算機(jī)在互聯(lián)網(wǎng)中的地址 / 位置的標(biāo)識
"14.215.177.38" : 表示百度服務(wù)器在互聯(lián)網(wǎng)中的IP地址
"www.baidu.com" : "14.215.177.38" 是一一對應(yīng)的
提示 : 域名比四分十進(jìn)制的IP表示法,更加好記憶
為什么通過域名就可以訪問到百度的服務(wù)器? DNS服務(wù)器(域名解析服務(wù)器)會把域名解析成IP地址
5.2.3 數(shù)據(jù)存放的路徑
數(shù)據(jù)存放在數(shù)據(jù)庫中的,數(shù)據(jù)庫是個(gè)硬件設(shè)備,類似電腦的磁盤;
類似于 : 磁盤里面存放數(shù)據(jù)是需要指定路徑的
5.2.4 URL的參數(shù)
參數(shù)就是告訴服務(wù)器我要什么樣的數(shù)據(jù),比如,要幾條數(shù)據(jù)...
6.HTTP協(xié)議
6.1 協(xié)議
6.1.1 協(xié)議概念 : 規(guī)定了請求和響應(yīng)的格式;還規(guī)定了URL的格式;還規(guī)定了請求怎么發(fā),響應(yīng)怎么發(fā);
6.1.2 協(xié)議作用 : 一旦規(guī)定好了請求和響應(yīng)的格式之后,那么服務(wù)器就可以讀懂客戶端的請求;而且客戶端也可以讀懂服務(wù)器的響應(yīng)
6.2 HTTP協(xié)議 : 超文本傳輸協(xié)議;
6.2.1 超文本 : 表示任何數(shù)據(jù)
6.2.2 超文本傳輸協(xié)議 : 表示可以傳輸任何數(shù)據(jù)
6.2.3 比較 : tel:// 只能打電話,不能傳輸超文本數(shù)據(jù)
7.HTTP協(xié)議特點(diǎn)
7.1 簡單 / 快速 / 靈活
7.2 HTTP協(xié)議版本
7.2.1 提示 : HTTP協(xié)議版本的選擇不是客戶端的事情,是服務(wù)決定的.不要瞎操心;
7.2.1 HTTP協(xié)議版本分為
HTTP 0.9 和 HTTP 1.0 "使用非持續(xù)鏈接"
1."非持續(xù)鏈接" : 一次鏈接只能處理一次請求和響應(yīng)
2.兩個(gè)計(jì)算機(jī)之間要想能夠傳輸數(shù)據(jù),必須先建立好鏈接
3.非持續(xù)鏈接,一旦發(fā)送一個(gè)請求,處理一個(gè)響應(yīng),鏈接就"立即斷開"
4.下次如果還要發(fā)送請求,需要再次建立鏈接
5.使用場景 : 對服務(wù)器資源占用要求高的APP
6.好處 : 可以及時(shí)釋放服務(wù)器的鏈接壓力
7.缺點(diǎn) : 每次請求和響應(yīng)之前都要建立鏈接,消耗資源
HTTP 1.1 "使用持續(xù)鏈接"
1."持續(xù)鏈接" : 一次鏈接可以處理多次請求和響應(yīng)
2.兩個(gè)計(jì)算機(jī)之間要想能夠傳輸數(shù)據(jù),必須先建立好鏈接
3.當(dāng)一次請求和響應(yīng)結(jié)束之后,那么這個(gè)"鏈接會持續(xù)一段時(shí)間"
4.在鏈接持續(xù)的時(shí)間內(nèi),可以發(fā)送多次請求和響應(yīng)
5."持續(xù)鏈接遲早還是會斷開的"
6.使用場景 : 對服務(wù)器資源占用要求高的APP
7.好處 : 可以及時(shí)釋放服務(wù)器的鏈接壓力
8.缺點(diǎn) : 每次請求和響應(yīng)之前都要建立鏈接,消耗資源
8.短連接和長連接和心跳包
8.1 短連接 : 包含非持續(xù)鏈接和持續(xù)鏈接
8.1.1 總之會斷開
8.1.2 能夠及時(shí)釋放服務(wù)器資源
8.1.3 讓服務(wù)器能夠?yàn)楦嗟挠脩籼峁┓?wù)
8.2 長連接
8.2.1 一旦建立鏈接就不會"主動(dòng)斷開";除非退出登錄,程序閃退,斷網(wǎng)...才會斷開鏈接
8.2.2 不能及時(shí)釋放服務(wù)器資源;那么就會對服務(wù)器的性能要求很高,要去服務(wù)器具備高并發(fā)性(能夠鏈接更多的用戶)
8.2.3 使用場景 : 需要數(shù)據(jù)及時(shí)到達(dá)的APP(及時(shí)通訊 : 微信,扣扣,陌陌...)
8.3 心跳包
8.3.1 是"檢測長連接"的重要手段
8.3.2 心跳包的發(fā)起者可以是客戶端,可以是服務(wù)器
9.請求和響應(yīng)
9.1 請求
請求行 : "GET / HTTP/1.1" 請求方法 空格 資源路徑 空格 協(xié)議版本
請求頭 : 客戶端告訴服務(wù)器一些額外信息,其中包括服務(wù)器地址(host : 必不可少)/設(shè)備環(huán)境...
請求體(可選) : GET請求是沒有請求體,只有POST請求有請求體
9.2 響應(yīng)
狀態(tài)行(響應(yīng)行) : "HTTP/1.1 200 OK" 協(xié)議版本 空格 狀態(tài)碼 狀態(tài)碼英文描述
響應(yīng)頭 : 服務(wù)器告訴客戶端的額外信息,其中包括服務(wù)器端的版本,服務(wù)器類型,文件在服務(wù)器大小,文件在服務(wù)器類型...
響應(yīng)體 : 客戶端發(fā)送請求的目的;就是保存在服務(wù)器數(shù)據(jù)庫里面的數(shù)據(jù)
10.NSURLConnection的使用
10.1 創(chuàng)建URL
10.2 創(chuàng)建請求 (NSURLRequest / NSMutableURLRequest)
10.3 異步發(fā)送請求,異步獲取數(shù)據(jù)
10.4 "如果獲取到服務(wù)器發(fā)送過來的響應(yīng)體(data : 二進(jìn)制) : 需要把二進(jìn)制反序列化,轉(zhuǎn)成客戶端可以直接使用的OC對象"
10.5 把反序列化之后的數(shù)據(jù)展示到控件上
11.網(wǎng)絡(luò)通信三要素
11.1 通過IP找服務(wù)器,通過端口號找處理請求的進(jìn)程,通過傳輸協(xié)議確定數(shù)據(jù)如何傳輸
12.UDP和TCP傳輸協(xié)議
12.1 UDP(數(shù)據(jù)報(bào)文協(xié)議)
12.1.1 相當(dāng)于廣播,數(shù)據(jù)在傳輸之前你不需要先建立鏈接
12.1.2 非安全的傳輸協(xié)議,容易丟包
12.1.3 流媒體,視頻的實(shí)時(shí)共享
12.2 TCP(數(shù)據(jù)控制協(xié)議)
12.2.1 相當(dāng)于打電話,數(shù)據(jù)在傳輸之前,計(jì)算機(jī)之間一定要先建立好鏈接
12.2.2 安全的傳輸協(xié)議,不容易丟包
12.2.3 使用場景,適用絕大多數(shù)APP
12.2.4 只要你的協(xié)議是HTTP / HTTPS協(xié)議,就表示你選擇的傳輸協(xié)議就是TCP
13.Socket開發(fā)體驗(yàn)
13.1 如果客戶端使用Socket進(jìn)行網(wǎng)絡(luò)開發(fā),需要做那幾件事情?
創(chuàng)建客戶端Socket
客戶端Socket鏈接到服務(wù)器端Socket
客戶端Socket向服務(wù)器Socket發(fā)送請求
客戶端Socket接收服務(wù)器Socket發(fā)送的響應(yīng)
關(guān)閉客戶端Socket
- (void)viewDidLoad {
[super viewDidLoad];
// 1.創(chuàng)建客戶端Socket
/**
參數(shù)
參數(shù)1 : domain,協(xié)議域/協(xié)議簇,AF_INET(IPV4的網(wǎng)絡(luò)開發(fā))
參數(shù)2 : type,Socket類型,SOCK_STREAM(TCP)/SOCK_DGRAM(UDP,報(bào)文)
參數(shù)3 : protocol,IPPROTO_TCP,協(xié)議,如果輸入0,可以根據(jù)第二個(gè)參數(shù),自動(dòng)選擇協(xié)議
提示 : SOCK_STREAM 表示請求是HTTP請求
返回值
int類型,如果 > 0 就表示成功,返回socket
clientSocket : 就是套接字描述符
*/
int clientSocket = socket(AF_INET, SOCK_STREAM, 0);
if (clientSocket > 0) {
NSLog(@"創(chuàng)建客戶端Socket成功");
}
// 2.客戶端Socket連接到服務(wù)器Socket
/**
參數(shù)
參數(shù)1 : 客戶端socket / 套接字描述符
參數(shù)2 : 指向數(shù)據(jù)結(jié)構(gòu)sockaddr的指針,其中包括目的端口和IP地址
參數(shù)3 : 結(jié)構(gòu)體數(shù)據(jù)長度
返回值 : int類型,返回0表示成功;反之,失敗;
*/
// 創(chuàng)建指向sockaddr_in的指針;這個(gè)結(jié)構(gòu)體里面封裝了端口號和IP
struct sockaddr_in addr;
// 設(shè)置協(xié)議域
addr.sin_family = AF_INET;
// 設(shè)置端口號
addr.sin_port=htons(80);
// 指定目標(biāo)計(jì)算機(jī)的IP
addr.sin_addr.s_addr = inet_addr("14.215.177.37");
int isConnected = connect(clientSocket, (const struct sockaddr *)&addr, sizeof(addr));
if (isConnected == 0) {
NSLog(@"客戶端Socket鏈接到服務(wù)器Socket成功");
}
// 3.客戶端Socket向服務(wù)器Socket發(fā)送請求
/**
參數(shù)
參數(shù)1 : 客戶端socket
參數(shù)2 : 發(fā)送內(nèi)容地址 void * == id
參數(shù)3 : 發(fā)送內(nèi)容長度
參數(shù)4 : 發(fā)送方式標(biāo)志,一般為0
返回值
如果成功,則返回發(fā)送的字節(jié)數(shù),失敗則返回SOCKET_ERROR
*/
// 請求的內(nèi)容 : 必須嚴(yán)格按照HTTP協(xié)議的規(guī)定去寫
NSString *sendMsg = @"GET / HTTP/1.1\r\n"
"Host: www.baidu.com\r\n"
"User-Agent: iphone\r\n"
"Connection: close\r\n\r\n"
;
// Socket把請求信息,發(fā)送給服務(wù)器
ssize_t sendLen = send(clientSocket, sendMsg.UTF8String, strlen(sendMsg.UTF8String), 0);
NSLog(@"%ld",sendLen);
// 4.客戶端Socket接收服務(wù)器Socket發(fā)送的響應(yīng)
/**
參數(shù)
參數(shù)1 : 客戶端socket
參數(shù)2 : 接收內(nèi)容的容器的地址
參數(shù)3 : 接收內(nèi)容緩存區(qū)長度
參數(shù)4 : 接收方式,0表示阻塞,必須等待服務(wù)器返回?cái)?shù)據(jù),才執(zhí)行這個(gè)函數(shù),服務(wù)器發(fā)一次數(shù)據(jù),就執(zhí)行一次
返回值
如果成功,則返回接收的字節(jié)數(shù),失敗則返回SOCKET_ERROR
*/
// 定義字符暫存區(qū) : 定義一個(gè)專門接收字符的數(shù)組,數(shù)組名就是數(shù)組的地址
u_int8_t buffer[1024];
// 先定義非0,保證第一次可以進(jìn)入循環(huán),一定要是負(fù)數(shù),因?yàn)榉?wù)器給你發(fā)送的字節(jié)數(shù)是正式
ssize_t recvLen = -1;
// 定義可變data,拼接buffer
NSMutableData *dataM = [NSMutableData data];
while (recvLen) {
// recv 默認(rèn)只接收一次,如果需要把完整的數(shù)據(jù)接收完,就需要在循環(huán)里面接收
recvLen = recv(clientSocket, buffer, sizeof(buffer), 0);
NSLog(@"%ld",recvLen);
// 循環(huán)拼接buffer
[dataM appendBytes:buffer length:recvLen];
}
// 字符串的反序列化
NSString *html = [[NSString alloc] initWithData:dataM encoding:NSUTF8StringEncoding];
NSLog(@"%@",html);
// 5.關(guān)閉客戶端Socket
close(clientSocket);
}