一、网络基础知识介绍
1、为什么要学习网络编程?---pptx介绍。
2、网络的基本概念---pptx介绍。
>什么是URL?
> HTTP简介
>网络开发解决方案
(一)、苹果原生(自带)方案
1> NSURLConnection
* iOS2.0出现,用法简单,最古老最经典最直接的一种方案。
*在iOS5.0之前,使用起来相对繁琐,一大堆的代理方法。
*在iOS5.0之后又作了一层改进,提供了两个非常方便的方法,使发送网络请求变得更简单。基本一句代码就能解决简单的网络处理了。
2> NSURLSession
* iOS7新出的技术,与NSURLConnection是并列的。
*但功能比NSURLConnection更加强大,性能也比NSURLConnection好很多
*当程序在前台时,NSURLSession和NSURLConnection大部分可以互相替代,但NSURLSession支持后台网络操作,除非用户强行关闭。
*苹果官方推荐使用NSURLSession代替NSURLConnection。
NSURLSession提供的功能:
1)通过URL将数据下载到内存;
2)通过URL将数据下载到文件系统;
3)将数据上传到指定的URL;
4)在后台完成上述功能.
5)支持下载,断点续传,后台上传/下载,后台上传/下载任务跟进
3> CFNetwork:NSURL*的底层,纯C语言,开发中几乎不会用到。
(二)、第三方框架
1> ASIHttpRequest:外号“HTTP终结者”,功能极其强大,几乎没有它考虑不到的问题,可惜2012年10月就停止更新,MRC环境。底层是CFNetwork。
2> AFNetworking:简单易用,提供了基本够用的常用功能,维护和使用者多,使用它程序员可以不用知道什么URL,什么是线程,什么是线程间的通信。底层是NSURLSession和NSURLConnection。
3> MKNetworkKit:简单易用,产自三哥的故乡印度,维护和使用者少。底层是NSURLConnection
>建议:为了提高开发效率,企业开发用的基本是第三方框架
3、NSURLConnection常用方法
>步骤
1)、创建NSURL对象,确定要访问的资源路径
2)、根据url创建请求对象NSURLRequest,向服务器索要数据
3)、建立网络链接,将请求对象(同步或异步)发送给服务器
>代码演示--访问百度
// 1、NSURL :确定要访问的资源路径
// m:mobile代表手机上访问的路径,一般大公司都会提供一个专门手机上访问的路径
NSURL *url = [NSURL URLWithString:@"http://m.baidu.com/"];
// 2、NSURLRequest:根据url创建请求对象,向服务器索要数据
NSURLRequest *reuqest = [NSURLRequest requestWithURL:url];
// 3、建立网络链接,将请求(同步或异步)发送给服务器
[NSURLConnection sendAsynchronousRequest:reuqest queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
NSLog(@"------%@",data);
}];
4、sendAsynchronousRequest方法和参数解释:
> sendAsynchronousRequest:是异步的,NSURLConnection会开启一条线程,发送网络请求。
> queue:队列-->负责调度/执行completionHandler的队列。
> completionHandler:完成请求的回调block。表示收到服务器的响应数据。
>如何选择队列?
*如果接收到数据后,需要直接更新UI,选择主队列。
*如果要做耗时操作,比如下载一个zip文件,下载完要进行解压缩操作,选择新建一个队列。
5、利用UIWebView加载请求百度返回的字符串---显示百度首页
// 1、NSURL :确定要访问的资源路径
NSURL *url = [NSURL URLWithString:@"http://m.baidu.com/"];
// 2、NSURLRequest:根据url创建请求对象,向服务器索要数据
NSMutableURLRequest *reuqest = [NSMutableURLRequest requestWithURL:url];
// 2.1、告诉服务器额外的信息
//告诉服务器我是iPhone
[reuqest setValue:@"iPhone AppleWebKit"forHTTPHeaderField:@"User-Agent"];
// 3、建立网络链接,将请求(同步或异步)发送给服务器
[NSURLConnection sendAsynchronousRequest:reuqest queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
//将二进制数据转换成字符串
NSString *html = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
// baseURL:加载资源的参照路径。
[self.webView loadHTMLString:html baseURL:url];
}];
> NSMutableURLRequest对象的作用?
*根据url创建请求对象,向服务器索要数据
*告诉服务器额外的信息:设置请求头和请求体。在网络访问过程中,绝大多数的变化都是通过request对象设置。比如身份验证,Cookie,浏览器类型,超时时长等。
二、Socket编程
1、网络通讯三要素
> IP地址[主机名],英文全称:Internet Protocol Address,又译为网际协议地址
*网络中设备的标识,用来唯一标识每一台计算机。通常现在常用的IP地址是IPV4地址。
* IPV4就是有4段数字,格式是xxx.xxx.xxx.xxx。每一段数字由8位二进制做成,取值范围是0~255。
* IPV4采用32位地址长度,只有大约43亿个地址。IPv4定义的有限地址空间将被耗尽。
*为了扩大地址空间,拟通过IPV6重新定义地址空间。IPv6采用128位地址长度。几乎可以不受限制地提供地址。但IPV6现在还没有正式普及。
*为了解决IPV4有限地址空间的问题,IP地址又分内网地址和外网地址。(比如校园网,每一个学生都会有一个内网地址,学校会有一个路由器,路由器会有个外网地址,学生想要上外网都必须通过路由器出去,只要通过同一个路由器出去的,他们对应的外网地址都是一样的)
*本质上所有的网络访问是通过ip地址访问的。域名是一个速记符号,不用记住IP地址复杂的数字。
*本地回环地址:127.0.0.1主机名:localhost
>每台计算机都有一个127.0.0.1
>如果127.0.0.1ping不通,说明网卡不工作(比如装黑苹果,检测网卡驱动有没装好,可以ping下回环地址)
>如果本机地址ping不通,说明网线坏了。
TIP:通过ip138.com可以速查某个域名对应的IP地址。
>端口号
1)、通过打电话例子说明端口号的作用
*很多网络概念来源于电话
*电话号码类似IP
*分机号类似于端口
2)、端口号的作用
*用来标识进程的逻辑地址,不同进程的标识。
*有效的端口:0~65535。
*其中0~1024由系统使用或保留端口。
*开发中不要使用1024以下的端口。
(端口有什么用呢?我们知道,一台拥有IP地址的主机可以提供许多服务,比如Web服务、FTP服务、SMTP服务等,这些服务完全可以通过1个IP地址来实现。那么,主机是怎样区分不同的网络服务呢?显然不能只靠IP地址,因为IP地址与网络服务的关系是一对多的关系。实际上是通过“IP地址+端口号”来区分不同的服务的。)
>传输协议(通信规则)--->(需要先学习OSI网络模型)
1)、UDP(用户数据报协议)
*面向无连接的协议
*只管发送,不确认对方是否接收到
*将数据资源和目的封装成数据包中,不需要建立连接
*每个数据包的大小限制在64K之内
*因为无需连接,因此是不可靠协议
*不需要建立连接,速度快
*理解发电报的特点就理解了UDP协议的特点。
/*
举例:地下党给组织或上级发电报。
*/
2)、TCP(Transmission Control Protocol,传输控制协议)
*面向连接的协议。
*建立连接,形成传输数据的通道
*在连接中进行大数据传输(数据大小不受限制)
*通过三次握手完成连接,是可靠协议,安全送达
*必须建立连接,效率会稍低
/*
简单的描述下三次握手的过程:主机A向主机B发出连接请求数据包:“我想给你发数据,可以吗?”,这是第一次对话;主机B向主机A发送同意连接和要求同步(同步就是两台主机一个在发送,一个在接收,协调工作)的数据包:“可以,你什么时候发?”,这是第二次对话;主机A再发出一个数据包确认主机B的要求同步:“我现在就发,你接着吧!”,这是第三次对话。三次“对话”的目的是使数据包的发送和接收同步,经过三次“对话”之后,主机A才向主机B正式发送数据。
*/
3)、使用场合
* tcp一般用于文件传输(ftp http对数据准确性要求高,速度可以相对慢),发送或接收邮件(pop imap smtp对数据准确性要求高,非紧急应用),远程登录(telnet ssh对数据准确性有一定要求,有连接的概念)等等;
* UDP一般用于即时通信(qq聊天对数据准确性和丢包要求比较低,但速度必须快),在线视频(rtsp速度一定要快,保证视频连续,但是偶尔花了一个图像帧,人们还是能接受的),网络语音电话(VoIP语音数据包一般比较小,需要高速发送,偶尔断音或串音也没有问题)等等。
网络通讯三要素归纳一句话:通过ip找机器,通过端口找程序,通过协议确定如何传输数据。
2、OSI网络模型
> OSI(Open System Interconnect),即开放式系统互联。一般都叫OSI参考模型,是ISO(国际标准化组织)组织在1985年研究的网络互联模型。
>该体系结构标准定义了网络互连的七层框架:物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。数据发送时,从第七层传到第一层,接收数据则相反。
三、Socket简介
1、pptx介绍。
2、socket的建立和连接
1>导入三个头文件
#import
#import
#import
2>创建socket
/**
参数
domain:协议域/协议族,AF_INET(IPV4的网络开发)
type: Socket类型,SOCK_STREAM(TCP)/SOCK_DGRAM(UDP,报文)
protocol: IPPROTO_TCP,协议,如果输入0,可以根据第二个参数自动选择协议
返回值
socket,如果>0就表示成功
*/
intclientSocket = socket(AF_INET, SOCK_STREAM,0);
3>连接到服务器
/**
参数
1>客户端socket
2>指向数据结构sockaddr的指针,其中包括目的端口和IP地址。即服务器的“结构体”地址
3>结构体数据长度
返回值
0成功/其他错误代号,非0即真
*/
structsockaddr_in serverAddress;
//协议族
serverAddress.sin_family = AF_INET;
// ip找机器
serverAddress.sin_addr.s_addr = inet_addr("127.0.0.1");
//端口号找程序
serverAddress.sin_port = htons(12345);
//连接服务器
intresult = connect(clientSocket, (conststructsockaddr *)&serverAddress,sizeof(serverAddress));
if(result ==0) {
NSLog(@"成功");
}else{
NSLog(@"失败");
}
TIP:
>在C语言开发时,如果要传递结构体的地址,通常会一起传递结构的长度。因为C语言中取数据是通过指针寻址的,告诉长度的目的是防止取错数据。
>在终端输入:nc -lk12345相当于在本机上启动了一个服务器,ip是本机地址,端口号是12345。
4>发送和接收数据
//发送数据
/**
参数
1>客户端socket
2>发送内容地址void * == id
3>发送内容长度,是指字节的长度。
4>发送方式标志,一般为0
返回值
如果成功,则返回发送的字节数,失败则返回SOCKET_ERROR
*/
NSString *msg =@"约?";
ssize_t sendLenght = send(clientSocket, msg.UTF8String, strlen(msg.UTF8String),0);
NSLog(@"发送了%ld长度的字节,字符串长度%zd",sendLenght,msg.length);
//接收数据
/**
参数
1>客户端socket
2>接收内容地址
3>长度,表示一次最多接收服务器返回的多少字节内容。
4>接收标志,一般填0,标示阻塞式的,一直等待服务器服务器返回数据
返回值
接收数据的长度
*/
//缓冲区,准备接受来自服务器的数据
// C语言中,数组的名字,就是指向数组第一个元素的指针。
uint8_t buffer[1024];
ssize_t recvLen = recv(clientSocket, buffer,sizeof(buffer),0);
NSLog(@"接收%ld字节",recvLen);
//获得服务器返回的二进制数据
NSData *data = [NSData dataWithBytes:buffer length:recvLen];
//将二进制数据转化成字符串
NSString *resultStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"接收到的内容是:%@",resultStr);
5>关闭连接
//断开连接
close(clientSocket);
四、Socket聊天示例
>补充:智能家居原理介绍。
五、通讯过程
1> socket发送http请求--->请求本地apache服务器
准备工作:
> Mac自带了Apache服务器,启动apache服务器。
>相关命令
* sudo apachectl -v,显示apache版本。
* sudo apachectl start,启动apache。
代码实现:
//建立连接
if(![selfconnectionToHost:@"127.0.0.1"port:80]) {
NSLog(@"失败");
return;
}
NSLog(@"成功");
//向服务器发送请求数据
NSString *result = [selfsendAndRecv:@"我要成为牛逼的程序员"];
NSLog(@"%@",result);
提问:给服务器发送的数据,服务器能接收到吗?会有响应结果吗?
>能接收到数据,但是不会有任何响应结果。原因是服务器不知道客户端发送的内容是什么。
思考
1)、客户端该传什么格式的数据给服务器?服务器才能看懂。
2)、服务器该返回什么格式的数据给客户端?客户端才能看懂。
//向服务器发送请求数据
//请求字符串,指定请求头和请求行
NSString *request =@"GET /abcd.txt HTTP/1.1\r\n"
"Host:localhost\r\n\r\n";
/**
URL与请求的对应关系:
比如URL是:http://localhost/abcd.txt其中协议头https是由HTTP/1.1指定的,主机地址是由Host:localhost指定的,路径是由/abcd.txt指定的
*/
NSString *result = [selfsendAndRecv:request];
NSLog(@"%@",result);
#获得本地apache服务器的根目录:
#在终端输入命令more /etc/apache2/httpd.conf回车
#搜索DocumentRoot得到/Library/WebServer/Documents
2> socket发送http请求--->请求远程服务器(百度,京东,起点)
/**
*连接远程服务器(百度,京东,起点)
*/
- (void)connectionToRometionServer{
//百度:域名m.baidu.comip:61.135.185.17
//起点:域名m.qidian.comip:36.250.76.204
//京东:域名m.jd.comip:111.206.227.150
//建立连接
if(![selfconnectionToHost:@"111.206.227.150"port:80]) {
NSLog(@"失败");
return;
}
NSLog(@"成功");
//向服务器发送请求数据
NSString *request =@"GET / HTTP/1.1\r\n"
"Host:m.jd.com\r\n"
"User-Agent:iPhone AppleWebKit\r\n"
"Connection:Close\r\n\r\n";
NSString *result = [selfsendAndRecv:request];
//在返回结果中查找\r\n\r\n,目的是取出响应状态行和响应头的内容
NSRange range = [result rangeOfString:@"\r\n\r\n"];
if(range.location != NSNotFound) {
NSString *html = [result substringFromIndex:range.location];
NSLog(@"=======> %@",html);
//加载网页
[self.webView loadHTMLString:html baseURL:[NSURL URLWithString:@"http://m.jd.com"]];
}
NSLog(@"--------%@",result);
}
#TIP:ping域名就能得到对应网站的ip地址。
非持续连接和持续连接的区别:
>非持续连接是指启动一次TCP连接服务器就向客户端传送一个对象,而持续连接是指服务器可在相同的TCP连接上向客户端发送多个对象。HTTP/1.0的默认设置是非持续连接,而HTTP/1.1的默认设置是持续连接。
>举个例子
在使用HTTP/1.0的情况下,如果打开一个包含一个HTML文件和10个内联图象对象的网页时,HTTP就要建立11次TCP连接才能把文件从服务器传送到客户端。而使用HTTP/1.1的情况下,如果打开同样的文件时,HTTP建立一次TCP连接就可把文件从服务器传送到客户端。
3> Http通讯过程
1、建立请求:
HTTP协议规定:一个完整的由客户端发给服务器的HTTP请求需要包含以下内容:
1)、请求行:指定请求方法、请求资源路径以及HTTP协议版本。
# /表示访问根目录
GET / HTTP/1.1
2)、请求头:对客户端的环境描述、客户端请求的主机地址等信息。
*请求头中至少包含以下信息
#客户端要访问的服务器主机地址
Host:m.baidu.com
*请求头中还可以包含以下信息
#客户端的类型,客户端的软件环境
User-Agent:iPhone AppleWebKit
#客户端所能接收的数据类型
Accept:text/html
#客户端的语言环境
Accept-Language:zh-cn
#客户端支持的数据压缩格式
Accept-Encoding:gzip
#访问结束后,是否断开连接
Connection:Close
3)、请求体(可选):客户端发给服务器的具体数据,例如要上传的文件数据。
请求格式:
>每一项请求信息末尾使用\r\n
>最后一个请求项末尾使用\r\n\r\n表示请求结束
#warming每一项请求信息和\r\n之间不能有空格。
2、接收响应
客户端向服务器发送请求,服务器应当做出响应,即返回给客户端的数据
HTTP协议规定:1个完整的HTTP响应中包含以下内容
1)、状态行:包含了HTTP协议版本、状态码、状态英文名称
#HTTP/1.1200OK
2)、响应头:包含了对服务器的描述、对返回数据的描述
#Server: Apache-Coyote/1.1//服务器的类型
#Content-Type: image/jpeg//返回数据的类型
#Content-Length:56811//返回数据的长度
#Date: Mon,23Jun201412:54:52GMT//响应的时间
3)、实体内容:服务器返回给客户端的具体数据,比如文件数据
七、NSURLConnection常用方法使用
1、服务器响应演练。
/**
*加载数据
*/
- (void)loadData{
// 1.创建url
NSURL *url = [NSURL URLWithString:@"http://pinyin.sogou.com/"];
// 2.创建请求对象
// NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setValue:@"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36"forHTTPHeaderField:@"User-Agent"];
// 3.发送异步请求到服务器(所有的网络请求都是耗时操作,因此绝大多数都是异步请求)
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
NSLog(@"%@---%@--%@---%@----%@",response,response.MIMEType,response.URL,response.textEncodingName,response.suggestedFilename);
[self.webView loadData:data MIMEType:response.MIMEType textEncodingName:response.textEncodingName baseURL:url];
}];
}
> response:本质上就是NSHTTPURLResponse从服务器上获得的响应
NSURLResponse相关属性:
- URL:响应url,一般用来重定向使用。浏览器演示什么是重定向,百度搜索搜狗输入法。(没有重定向的情况下,响应url和请求url是相同)
- MIMEType:请求数据的数据类型,服务器告诉客户端的返回的数据是什么类型。
Content-Type等价MIMEType,客户端根据MIMEType决定用什么来打开或显示返回的数据。(典型的列子就是浏览器装flash插件的例子。当在浏览器中看视频的时候,浏览器都会提示要安装flash插件,否则无法观看,浏览器就是通过MIMEType来判断观看视频需要flash插件的支持。)
- textEncodingName:返回内容的编码方式
以下两个属性通常用于开发下载
- expectedContentLength:请求二进制数据的长度,下载文件的大小
- suggestedFilename:建议保存的文件名,服务器建议下载文件保存时使用的文件名,一般mac下下载文件不需要填写保存的文件名,就是因为浏览器客户端根据服务器返回的该字段作为文件名了。
2、错误处理:在实际开发中,一定要处理错误!任何的网络请求都有可能出错!比如流量没了,网络断了,没信号了。
//有时候没有错误,但也没有数据
if(connectionError !=nil|| data ==nil) {
//提示用户最好友善点,不要太专业了。比如提示出现404错误,或500错误了。用户不会理解这些专业术语的。
NSLog(@"你的网络不给力哦!");
return;
}
3、超时时长和缓存策略
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:0timeoutInterval:15];
- cachePolicy:缓存策略
NSURLRequestUseProtocolCachePolicy =0,默认的缓存策略
NSURLRequestReloadIgnoringLocalCacheData =1,忽略本地缓存数据
一般应用于对数据‘实时性要求高’的应用每次都从服务器加载数据
应用场景:12306,股票,彩票等
NSURLRequestReloadIgnoringLocalAndRemoteCacheData =4,没有实现的缓存策略,可忽略
NSURLRequestReloadIgnoringCacheData = NSURLRequestReloadIgnoringLocalCacheData,
//以下两项做离线应用
//在实际开发中,要尽量让用户回到网络上!
NSURLRequestReturnCacheDataElseLoad =2,有缓存,就返回缓存数据,否则从服务器中加载。
NSURLRequestReturnCacheDataDontLoad =3,有缓存,就返回缓存数据,否则不加载。
如果应用需要通过广告,展现率,点击率,成交率来获得收入的,建议不要做离线缓存,原因主要有两点:
1>开发困难且周期长,需要设计两个数据库,一个本地数据库,用来缓存数据,一个远程数据库。
2>广告,展现率,点击率,成交率等操作都是基于网络的,离线不使用网络就无法产生收入。
NSURLRequestReloadRevalidatingCacheData =5,没有实现的缓存策略,可忽略
- timeoutInterval:请求的超时时长,在指定的时间内,如果没有收到服务器的反馈,认为请求失败。
系统默认60s
SDWebImage超时时长15s
AFN超时时长60s
建议:不要太短,也不要太长。在15s~30s之间最合适