1.为什么学习网络?
1.1 学习网络是学习实时更新数据的手段
1.2 掌握了实时更新数据的手段,可以使APP变得更加有吸引力
1.3 数据的实时的更新是在服务器端发生的
1.4 客户端只需要把服务器最新的数据加载到客户端,然后展示即可
1.5 客户端的网络开发只做一件事,向服务器发送网络请求,得到服务器的"最新"数据展示在界面上
1.6 客户端的开发者,只需要关心"请求怎么发,响应怎么处理"
2.网络核心
2.1 客户端 : 就是手机 / APP
2.2 服务器端 : 为客户端提供数据的"特殊"的计算机
2.3 请求 : 客户端向服务器端获取数据的行为
2.4 响应 : 服务器端对客户端的请求作出的反应
3.网络开发的结构
3.1 客户端 : 发送请求,告诉服务器自己要什么数据
3.2 服务器端 : 服务器得到客户端的请求之后,就去数据库里面找客户端需要的数据,如果找到就把数据发送客户端
3.3 数据库 : 专门存放数据的地方
3.4 实际开发中,作为移动端开发,只需要关心客户端的开发就可以了
4.服务器
4.1 测试服务器 : 在开发阶段使用的服务器,是本地的,所以数据加载比较快,方便前后端开发者调节数据
4.2 正式服务器 : APP发布上线之后,访问的服务器;里面的数据都是正确的,可以被任何备用户访问
4.3 黑马学习网络课程,选择的是本地apache服务器,只在学习时使用;实际开发,使用自己公司的测试和正式服务器
5.URL
http://open.api.yaolan.com/api/bbs/post?limit=20&start=0&source=ios&tid=53251140&token=3784
5.1 URL的概念 : 统一资源定位符 (数据在网络中的路径 / 地址)
5.1.1 通过唯一的URL可以获取到网络中唯一的数据
5.1.2 每个人都有住址.URL就是类似人的住址.
5.2 URL的格式
5.2.1 协议头
http:// 表示传输任何数据
https:// 表示传输任何安全数据
ftp:// 表示传输大文件
tel:// 表示打电话的 (tel://18510000001)
sms:// 表示发送短信 (sms://18510000001)
mailto:// 表示发送邮件 (mailto://zhangjiesharp@163.com)
5.2.2 服务器地址 / 域名 / 服务器IP
"open.api.yaolan.com" : 表示向哪个公司的服务器获取数据
"www.baidu.com" : 表示向百度公司的服务器获取数据
服务器地址 服务器地址 / 域名 / 服务器IP : 表示这个计算机在互联网中的地址 / 位置的标识
"14.215.177.38" : 表示百度服务器在互联网中的IP地址
"www.baidu.com" : "14.215.177.38" 是一一对应的
提示 : 域名比四分十进制的IP表示法,更加好记忆
为什么通过域名就可以访问到百度的服务器? DNS服务器(域名解析服务器)会把域名解析成IP地址
5.2.3 数据存放的路径
数据存放在数据库中的,数据库是个硬件设备,类似电脑的磁盘;
类似于 : 磁盘里面存放数据是需要指定路径的
5.2.4 URL的参数
参数就是告诉服务器我要什么样的数据,比如,要几条数据...
6.HTTP协议
6.1 协议
6.1.1 协议概念 : 规定了请求和响应的格式;还规定了URL的格式;还规定了请求怎么发,响应怎么发;
6.1.2 协议作用 : 一旦规定好了请求和响应的格式之后,那么服务器就可以读懂客户端的请求;而且客户端也可以读懂服务器的响应
6.2 HTTP协议 : 超文本传输协议;
6.2.1 超文本 : 表示任何数据
6.2.2 超文本传输协议 : 表示可以传输任何数据
6.2.3 比较 : tel:// 只能打电话,不能传输超文本数据
7.HTTP协议特点
7.1 简单 / 快速 / 灵活
7.2 HTTP协议版本
7.2.1 提示 : HTTP协议版本的选择不是客户端的事情,是服务决定的.不要瞎操心;
7.2.1 HTTP协议版本分为
HTTP 0.9 和 HTTP 1.0 "使用非持续链接"
1."非持续链接" : 一次链接只能处理一次请求和响应
2.两个计算机之间要想能够传输数据,必须先建立好链接
3.非持续链接,一旦发送一个请求,处理一个响应,链接就"立即断开"
4.下次如果还要发送请求,需要再次建立链接
5.使用场景 : 对服务器资源占用要求高的APP
6.好处 : 可以及时释放服务器的链接压力
7.缺点 : 每次请求和响应之前都要建立链接,消耗资源
HTTP 1.1 "使用持续链接"
1."持续链接" : 一次链接可以处理多次请求和响应
2.两个计算机之间要想能够传输数据,必须先建立好链接
3.当一次请求和响应结束之后,那么这个"链接会持续一段时间"
4.在链接持续的时间内,可以发送多次请求和响应
5."持续链接迟早还是会断开的"
6.使用场景 : 对服务器资源占用要求高的APP
7.好处 : 可以及时释放服务器的链接压力
8.缺点 : 每次请求和响应之前都要建立链接,消耗资源
8.短连接和长连接和心跳包
8.1 短连接 : 包含非持续链接和持续链接
8.1.1 总之会断开
8.1.2 能够及时释放服务器资源
8.1.3 让服务器能够为更多的用户提供服务
8.2 长连接
8.2.1 一旦建立链接就不会"主动断开";除非退出登录,程序闪退,断网...才会断开链接
8.2.2 不能及时释放服务器资源;那么就会对服务器的性能要求很高,要去服务器具备高并发性(能够链接更多的用户)
8.2.3 使用场景 : 需要数据及时到达的APP(及时通讯 : 微信,扣扣,陌陌...)
8.3 心跳包
8.3.1 是"检测长连接"的重要手段
8.3.2 心跳包的发起者可以是客户端,可以是服务器
9.请求和响应
9.1 请求
请求行 : "GET / HTTP/1.1" 请求方法 空格 资源路径 空格 协议版本
请求头 : 客户端告诉服务器一些额外信息,其中包括服务器地址(host : 必不可少)/设备环境...
请求体(可选) : GET请求是没有请求体,只有POST请求有请求体
9.2 响应
状态行(响应行) : "HTTP/1.1 200 OK" 协议版本 空格 状态码 状态码英文描述
响应头 : 服务器告诉客户端的额外信息,其中包括服务器端的版本,服务器类型,文件在服务器大小,文件在服务器类型...
响应体 : 客户端发送请求的目的;就是保存在服务器数据库里面的数据
10.NSURLConnection的使用
10.1 创建URL
10.2 创建请求 (NSURLRequest / NSMutableURLRequest)
10.3 异步发送请求,异步获取数据
10.4 "如果获取到服务器发送过来的响应体(data : 二进制) : 需要把二进制反序列化,转成客户端可以直接使用的OC对象"
10.5 把反序列化之后的数据展示到控件上
11.网络通信三要素
11.1 通过IP找服务器,通过端口号找处理请求的进程,通过传输协议确定数据如何传输
12.UDP和TCP传输协议
12.1 UDP(数据报文协议)
12.1.1 相当于广播,数据在传输之前你不需要先建立链接
12.1.2 非安全的传输协议,容易丢包
12.1.3 流媒体,视频的实时共享
12.2 TCP(数据控制协议)
12.2.1 相当于打电话,数据在传输之前,计算机之间一定要先建立好链接
12.2.2 安全的传输协议,不容易丢包
12.2.3 使用场景,适用绝大多数APP
12.2.4 只要你的协议是HTTP / HTTPS协议,就表示你选择的传输协议就是TCP
13.Socket开发体验
13.1 如果客户端使用Socket进行网络开发,需要做那几件事情?
创建客户端Socket
客户端Socket链接到服务器端Socket
客户端Socket向服务器Socket发送请求
客户端Socket接收服务器Socket发送的响应
关闭客户端Socket
- (void)viewDidLoad {
[super viewDidLoad];
// 1.创建客户端Socket
/**
参数
参数1 : domain,协议域/协议簇,AF_INET(IPV4的网络开发)
参数2 : type,Socket类型,SOCK_STREAM(TCP)/SOCK_DGRAM(UDP,报文)
参数3 : protocol,IPPROTO_TCP,协议,如果输入0,可以根据第二个参数,自动选择协议
提示 : SOCK_STREAM 表示请求是HTTP请求
返回值
int类型,如果 > 0 就表示成功,返回socket
clientSocket : 就是套接字描述符
*/
int clientSocket = socket(AF_INET, SOCK_STREAM, 0);
if (clientSocket > 0) {
NSLog(@"创建客户端Socket成功");
}
// 2.客户端Socket连接到服务器Socket
/**
参数
参数1 : 客户端socket / 套接字描述符
参数2 : 指向数据结构sockaddr的指针,其中包括目的端口和IP地址
参数3 : 结构体数据长度
返回值 : int类型,返回0表示成功;反之,失败;
*/
// 创建指向sockaddr_in的指针;这个结构体里面封装了端口号和IP
struct sockaddr_in addr;
// 设置协议域
addr.sin_family = AF_INET;
// 设置端口号
addr.sin_port=htons(80);
// 指定目标计算机的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链接到服务器Socket成功");
}
// 3.客户端Socket向服务器Socket发送请求
/**
参数
参数1 : 客户端socket
参数2 : 发送内容地址 void * == id
参数3 : 发送内容长度
参数4 : 发送方式标志,一般为0
返回值
如果成功,则返回发送的字节数,失败则返回SOCKET_ERROR
*/
// 请求的内容 : 必须严格按照HTTP协议的规定去写
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把请求信息,发送给服务器
ssize_t sendLen = send(clientSocket, sendMsg.UTF8String, strlen(sendMsg.UTF8String), 0);
NSLog(@"%ld",sendLen);
// 4.客户端Socket接收服务器Socket发送的响应
/**
参数
参数1 : 客户端socket
参数2 : 接收内容的容器的地址
参数3 : 接收内容缓存区长度
参数4 : 接收方式,0表示阻塞,必须等待服务器返回数据,才执行这个函数,服务器发一次数据,就执行一次
返回值
如果成功,则返回接收的字节数,失败则返回SOCKET_ERROR
*/
// 定义字符暂存区 : 定义一个专门接收字符的数组,数组名就是数组的地址
u_int8_t buffer[1024];
// 先定义非0,保证第一次可以进入循环,一定要是负数,因为服务器给你发送的字节数是正式
ssize_t recvLen = -1;
// 定义可变data,拼接buffer
NSMutableData *dataM = [NSMutableData data];
while (recvLen) {
// recv 默认只接收一次,如果需要把完整的数据接收完,就需要在循环里面接收
recvLen = recv(clientSocket, buffer, sizeof(buffer), 0);
NSLog(@"%ld",recvLen);
// 循环拼接buffer
[dataM appendBytes:buffer length:recvLen];
}
// 字符串的反序列化
NSString *html = [[NSString alloc] initWithData:dataM encoding:NSUTF8StringEncoding];
NSLog(@"%@",html);
// 5.关闭客户端Socket
close(clientSocket);
}
网友评论