網絡基礎: 1.二進制數據流
重點:1.了解網絡中傳輸的都是二進制數據流. 2.了解網絡編程概念.
{
問題:為什么網絡中傳遞的都是二進制數據? 因為物理層只能傳遞電信號(1和0);
// 從網絡中接收到的信息: 普通的字符串/圖片/視頻/文件 都是二進制數據嗎? 都是!
// 從網絡中接收的時 JSON 數據或者 XML 數據! 本質上也是二進制數據!
認識網絡:
// 網絡概念 <1> 經常見到的: 網卡/網線/IP地址/子網掩碼/路由地址/DNS服務器地址 作用?
// <2> 容易忽略的:MAC地址/數據/數據包
// <3> 網絡編程的概念:客戶端/服務器/請求/響應/數據流
// 網絡是數據交互的媒介,我們通過網絡得到服務器上的數據,也是通過網絡給服務器傳遞數據.
// 也就是說,網絡的實質,是交互數據.
0.移動網絡應用 = 良好的UI + 良好的用戶體驗 + 實時更新的數據
1.網絡是應用的靈魂,是所有應用的數據來源.離開了網絡,我們的應用就是一潭死水.
網絡編程概念:
<1>客戶端(Client):移動設備(手機/iPad等手持設備).
客戶端一般就是前端/前臺等等.iOS,android開發都是前端開發.
<2>服務器(Server):為客戶端提供服務(比如數據/資源等)的機器---本質也是一臺計算機(+服務器軟件).
服務器開發就是后端/后臺開發.java/php/.net等.
<3>請求(Request):客戶端向服務器索取數據.
<4>響應(Response):服務器對客戶端請求做出的反應,一般就是返回數據給客戶端.
服務器:按開發階段來分,分為兩種:
遠程服務器: 外網服務器.應用上線之后供全體用戶使用的服務器.速度取決于用戶的網速和服務器的性能.
本地服務器: 內網服務器,測試服務器.開發測試階段使用的服務器.供內部開發測試人員使用.速度飛快.
2.網絡中傳輸的都是二進制數據流. html/圖片/視頻數據...
二進制數據流是如何被分組并傳輸的呢?
}
網絡基礎: 2.七層協議
重點:1.理解網絡 2.理解七層協議/五層模型 3.理解Socket.
{
應用層: 規定"應用程序"的數據格式. http / ftp /email 等. //紙條上寫的是啥?
傳輸層: 建立"端口"到"端口"之間的通信. UDP/TCP 協議."端口". //我們幫你傳紙條
網絡層: 確定每一臺計算機的位置,建立"主機"到"主機"之間的通信.IPv4協議,"IP地址". // 女孩的位置
數據鏈路層: 確定1和0的分組方式.以太網協議:一組電信號就是一個數據包."MAC地址"/網卡/廣播. // 深情告白
物理層: 將電腦連接入網絡,傳輸電信號1和0. // 一張白紙
互聯網分層結構的好處:
上層的變動完全不影響下層的結構.
Socket : "主機 + 端口"就是"Socket(套接字/插座)" ----- TCP/IP協議
}
網絡基礎: 3.數據包/流
重點:1.理解數據包. 2.理解網絡通信實質.
{
網絡通信的基礎: 知道對方的MAC地址和IP地址.
網絡通信的實質: 互相交換數據包.
數據包:
每一個數據包都包含 "標頭"和"數據"兩個部分."標頭"包含本數據包的一些說明."數據"則是本數據包的內容.
以太網數據包: 最基礎的數據包.標頭部分包含了通信雙方的MAC地址,數據類型等. '標頭'長度:18字節,'數據'部分長度:46~1500字節.
IP數據包: 標頭部分包含通信雙方的IP地址,協議版本,長度等信息. '標頭'長度:20~60字節,"數據包"總長度最大為65535字節.
TCP/UDP數據包:標頭部分包含雙方的發出端口和接收端口. UDP數據包:'標頭'長度:8個字節,"數據包"總長度最大為65535字節,正好放進一個IP數據包. TCP數據包:理論上沒有長度限制,但是,為了保證網絡傳輸效率,通常不會超過IP數據長度,確保單個包不會被分割.
應用程序數據包: 標頭部分規定應用程序的數據格式.數據部分傳輸具體的數據內容.
嵌套:
數據包層層嵌套,上一層數據包嵌套在下一層數據包的數據部分.最后通通由以太網數據包來進行數據傳遞.
分包/拆包:
一般傳遞的數據都比較大,會將數據包分割成很多個部分來傳遞.
拼包:
將接收到數據包按序號拼接起來,組成完整的數據包.
}
網絡基礎: 4.IP地址
重點:了解IP地址.
{
靜態IP地址:
固定不變的IP地址,需要用戶自己手動設置.
動態IP地址:
通過DHCP協議自動生成的IP地址.
DHCP協議:
通過DHCP協議,用戶獲得本機的動態IP地址,子網掩碼,網關,DNS服務器等.
子網掩碼:
與IP地址配合使用判斷兩臺計算機是否位于同一個子網絡.
DNS服務器:
可以將域名(網址)轉換成IP地址.
}
網絡基礎: 5.一個HTTP請求
重點:了解一個HTTP請求的完整過程.
{
對之前所學內容的一個系統的演示.
1. URL(Uniform Resource Locator):
統一資源定位符.URL就是資源的地址,位置.通過一個URL能夠找到互聯網上唯一的一個資源.
URL的基本格式: 協議://主機地址/路徑
協議:不同的協議代表不同的資源查找方式,資源傳輸方式.
{
URL中的常見協議:
<1>HTTP:超文本傳輸協議,在網絡開發中最常用的協議.訪問的是遠程的網絡資源.格式:http://...
<2>file:訪問的時本地計算機上的資源.格式:file://(不要再加主機地址了)
<3>FTP:訪問的是共享主機的文件資源.格式:ftp://
<4>mailto:訪問的是電子郵件地址.格式:mailto:
}
主機地址:存放資源的主機IP地址(域名).
路徑:資源在主機中得具體位置.
2. HTTP請求的完整過程:
<1> 請求: 客戶端發出請求.向服務器索要數據(操作數據).
<2> 響應: 服務器對客戶端的請求做出響應.返回客戶端所需要的數據.
3. 包裝一個HTTP請求
用 NSURLRequest 來包裝一個HTTP請求.可以指定緩存策略和超時時間.
1> 緩存策略的選擇:NSURLRequestCachePolicy
{
NSURLRequestUseProtocolCachePolicy = 0,
// 默認的緩存策略,使用協議定義.
NSURLRequestReloadIgnoringLocalCacheData = 1,
// 忽略本地緩存,直接從原始服務器地址下載.
NSURLRequestReturnCacheDataElseLoad = 2,
// 只有在緩存中不存在數據時,才從原始地址下載
NSURLRequestReturnCacheDataDontLoad = 3,
// 只使用緩存數據,如果不存在緩存,則請求失敗. 用于沒有網絡連接的離線模式
NSURLRequestReloadIgnoringLocalAndRemoteCacheData = 4,
// 忽略遠程和本地的數據緩存,直接從原始地址下載
NSURLRequestReloadIgnoringCacheData = NSURLRequestReloadIgnoringLocalCacheData = 1,
// 忽略緩存,直接從原始服務器地址下載.
NSURLRequestReloadRevalidatingCacheData = 5,
// 驗證本地數據和遠程數據是否相同,如果不同則下載遠程數據,否則使用本地數據.
}
// 網絡數據緩存
網絡緩存數據,保存在SQLite的數據庫中(NSHomeDirectory()),
//查看緩存的數據命令行:
cd 文件目錄 (打開文件目錄)
ls 查看當前文件下目錄
sqlite3 Cache.db 打開數據庫
.tables 查看數據庫中的表單
select * from cfurl_cache_response; 查看服務器響應緩存
select * from cfurl_cache_receiver_data; 查看服務器返回的數據緩存
2> 默認的超時時間: timeoutInterval = 60
4. 發送請求
用 NSURLConnection 發送請求.
同步方法:一般只有在網絡下載的時候使用!利用這個方法首先得到服務器中需要下載的數據信息,然后由用戶選擇是否下載!
+ (NSData *)sendSynchronousRequest:(NSURLRequest *)request returningResponse:(NSURLResponse **)response error:(NSError **)error;
異步方法:
+ (void)sendAsynchronousRequest:(NSURLRequest*) request queue:(NSOperationQueue*) queue
completionHandler:(void (^)(NSURLResponse* response, NSData* data, NSError* connectionError)) handler
"iPhone AppleWebKit" 制定客戶端類型
}
網絡基礎: 6.Socket演練
重點:"理解"什么是Socket.
{
0.nc -lk 端口號 :始終監聽本地計算機此端口的數據.
1.導入三個頭文件
{
#import <sys/socket.h>
#import <netinet/in.h>
#import <arpa/inet.h>
}
2.Socket書寫步驟
{
1.創建客戶端Socket socket(<#int#>, <#int#>, <#int#>);
2.創建服務器Socket struct sockaddr_in serverAddress;
3.連接到服務器(Socket編程) connect(<#int#>, <#const struct sockaddr *#>, <#socklen_t#>);
4.發送數據給服務器 send(<#int#>, <#const void *#>, <#size_t#>, <#int#>)
5.接收服務器返回的數據 recv(<#int#>, <#void *#>, <#size_t#>, <#int#>)
6.關閉 Socket close(socketNumber)
}
/*
創建客戶端 Socket.
三個參數: domain:網絡地址類型 type:端口類型 protocal:傳輸協議
domain:協議域 指定socket主機地址類型. 網絡層協議 AF_INET/IPv4協議; AF_INET_6/IPv6協議
type:指定Socket端口類型. 指定傳輸層協議類型(TCP/UDP),SOCK_STREAM(TCP/流) ,SOCK_DGRAM(UDP/報文頭)
protocal:指定傳輸協議:常用協議:IPPROTO_TCP、IPPROTO_UDP等,分別對應TCP傳輸協議、UDP傳輸協議.
最后一個參數傳0,會根據第二個參數,自動選擇第二個參數對應的協議.
返回值:如果 > 0 表示成功.
*/
// 0.創建客戶端 Socket.
int socketNumber = socket(AF_INET, SOCK_STREAM, 0);
if (socketNumber > 0) {
NSLog(@"Socket創建成功:%d",socketNumber);
}else{
NSLog(@"Socket創建失敗");
};
/*
連接到服務器.
三個參數:
1.客戶端socket.
2.接收方的socket參數.
3.數據長度.
返回值: 0 表示成功,其他: 錯誤代號.
*/
// 1.服務器socket
struct sockaddr_in serverAddress;
// IPv4協議.
serverAddress.sin_family = AF_INET;
// 接收方(服務器)IP地址.
serverAddress.sin_addr.s_addr = inet_addr("127.0.0.1");
// 端口號.
serverAddress.sin_port = htons(56789);
// 2.連接到服務器
// serverAddress 的數據長度.
socklen_t length = sizeof(serverAddress);
// 連接服務器.
// 在C語言中,傳遞結構體的時候,會指定結構體的長度
// &取的是數據的起始位置,只有傳遞一個數據的長度,才能夠保證拿到完整的結構體數據.
// 返回值:0成功,其他都是失敗.
int connection = connect(socketNumber, (const struct sockaddr *)&serverAddress,length);
if (!connection) {
NSLog(@"連接成功%d",connection);
}else{
NSLog(@"連接失敗");
}
/*
發送消息到服務器
參數:
1> 客戶端Socket.
2> 發送內容地址.
3> 發送內容長度.
4> 發送方式標識,一般為0.
*/
// 3.發送消息到服務器
// 發送消息內容
NSString *msg = @"hello socket!";
msg.length :表示的是OC字符串的長度.
msg.UTF8String :將OC字符串轉換成 UTF8 的 ASCII 碼,一個漢字需要占用3個字節的長度.
strlen :計算所有 ASCII 碼的長度.
// 發送消息
ssize_t result = send(socketNumber, msg.UTF8String, strlen(msg.UTF8String), 0);
NSLog(@"result = %ld",result);
/*
接收服務器接返回的消息
參數:
1> 客戶端Socket.
2> 接收內容緩存區.
3> 接收內容緩存區長度.
4> 接收方式.0表示阻塞式.必須等待服務器返回數據.
返回值:
如果成功,則返回接收到的字節數.失敗則返回SOCKET_ERROR
*/
// 4.服務器接收消息
// 創建接收內容緩存區.
uint8_t buffer[1024];
// 接受消息
ssize_t len = recv(socketNumber, buffer, sizeof(buffer), 0);
NSLog(@"len: %zd",len);
// 取出接受內容緩存區中的數據.
NSData *data = [NSData dataWithBytes:buffer length:len];
// 將二進制流數據data轉換成字符串類型.
NSString *receive = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"receive:%@",receive);
// 5.關閉Socket
close(socketNumber);
}
網絡基礎: 7.本地服務器的搭建
{
網絡常識:
本地主機IP地址:IPv4地址. ----不通,說明網線有問題.
本地主機回環地址:127.0.0.1 ---不通,表示網卡不正常.
本地主機名:localhost ---不通,表示網卡不正常.
路由器:負責向不同的子網絡傳輸數據.
域名:是IP地址的一個速記符號.最終都會由DNS服務器解析成IP地址.
}