一.Cocoa网络编程框架

Cocoa 中网络编程层次结构分为三层,自上而下分别是:

  • Cocoa 层:NSURL,Bonjour,Game Kit,WebKit
  • Core Foundation 层:基于 C 的 CFNetwork 和 CFNetServices
  • OS 层:基于 C 的 BSD socket

在应用层我们一般进行HTTP客户端和Socket客户端的开发工作。

二.HTTP编程

HTTP:Hyper Text Transfer Protocol(超文本传输协议)构建于TCP/IP协议之上,默认端口号是80,无连接无状态的一种网络应用层协议,它常用于Web中HTML文档的传输。它是一种响应式的结构,即Request-Response模式,除非使用长连接不然它会应答一次后断开连接。

报文基本格式由三部分组成:状态行请求头/响应头消息主体/响应正文

<method> <request-URL> <version>
<headers>
<entity-body>

URL全称是资源描述符,我们可以这样认为:一个URL地址,它用于描述一个网络上的资源。

HTTP定义了与服务器中URL交互的不同方法,最基本的方法有4种,分别是GETPOSTPUTDELETE对应着对这个资源的查,增,改,删4个操作。其中最为常用的是GETPOST这两种请求。

request:

 GET /books/?sex=man&name=Professional HTTP/1.1
 Host: www.example.com
 User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6)
 Gecko/20050225 Firefox/1.0.1
 Connection: Keep-Alive

response:

HTTP/1.1 200 OK

Server:Apache Tomcat/5.0.12
Date:Mon,6Oct2003 13:23:42 GMT
Content-Length:112

<html>
    ......
</html>
常用的数据交互格式

服务器在Response中返回给客户端的数据,一般是文本数据或者字节数据。常见的文本数据格式有JSON或者XML格式。

JSON(JavaScript Object Notation):一种轻量级的数据交换格式,具有良好的可读和便于快速编写的特性,可在不同平台之间进行数据交互。它的格式采用Key-Value的形式:

{"name" : "jack", "age" : 10}
{"names" : ["jack", "rose", "jim"]}

XML(Extensible Markup Language) :用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言,它是一种元素节点树形结构。

<?xml version="1.0" encoding="UTF-8" ?> //一个元素节点
长连接模式

当使用普通模式,即非 Keep-Alive 模式时,每个请求/应答客户和服务器都要新建一个连接,完成之后立即断开连接(HTTP 协议为无连接的协议);当使用 Keep-Alive 模式(又称持久连接、连接重用)时,Keep-Alive 功能使客户端到服务器端的连接持续有效,当出现对服务器的后继请求时,Keep-Alive 功能避免了建立或者重新建立连接。

  • HTTP Keep-Alive 简单说就是保持当前的TCP连接,避免了重新建立连接。
  • HTTP 长连接不可能一直保持,例如Keep-Alive: timeout=5, max=100,表示这个TCP通道可以保持5秒,max=100,表示这个长连接最多接收100次请求就断开。
  • HTTP 是一个无状态协议,这意味着每个请求都是独立的,Keep-Alive 没能改变这个结果。另外,Keep-Alive也不能保证客户端和服务器之间的连接一定是活跃的,在 HTTP1.1 版本中也如此。唯一能保证的就是当连接被关闭时你能得到一个通知,所以不应该让程序依赖于 Keep-Alive 的保持连接特性,否则会有意想不到的后果。
iOS中HTTP客户端

苹果原生

  • NSURLConnection:用法简单,最古老最经典最直接的一种方案(API已经弃用)
  • NSURLSession:功能比NSURLConnection更加强大,苹果目前比较推荐使用这种技术
  • CFNetwork:NSURL*的底层,纯C语言。

第三方框架

  • AFNetworking:简单易用,提供了基本够用的常用功能,维护和使用者多。(推荐使用)
  • ASIHttpRequest:外号“HTTP终结者”,功能极其强大,可惜早已停止更新。
  • MKNetworkKit:简单易用,产自印度,维护和使用者少。
NSURLSession简单使用
//创建URL
NSURL * url = [NSURL URLWithString:@"http://192.168.1.200/login.php?username=haha&password=123"];

//创建Session
NSURLSession * session = [NSURLSession sharedSession];

//创建任务
NSURLSessionDataTask * task = [session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
    NSLog(@"%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
}];

//开启网络任务
[task resume];
AFNetworking简单使用
AFHTTPSessionManager *mgr = [AFHTTPSessionManager manager];

//添加返回的值的类型
mgr.responseSerializer = [AFHTTPResponseSerializer serializer];

[mgr GET:@"http://127.0.0.1:8888/test.jpg" parameters:nil progress:^(NSProgress * _Nonnull downloadProgress) {
    //如果要显示进度,就要来到这里,由于请求下来的数据是data,用代理方法是一段一段下来的,所以只要下来一段,就会执行这个block,所有用当前进度除以总进度就会展现出下载的进度条
    NSLog(@"进度 = %f",1.0 * downloadProgress.completedUnitCount / downloadProgress.totalUnitCount);

} success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
    //成功就会走这里,responseObject是字典或者数组
    NSLog(@"%@",responseObject);

} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
    //失败就会走到这里
    NSLog(@"err = %@",error);
}];

三.Socket(TCP/UDP)编程

TCP协议
  • TCP 提供一种面向连接的、可靠的字节流服务。
  • 在一个 TCP 连接中,仅有两方进行彼此通信,广播和多播不能用于 TCP。
  • TCP 使用校验和,确认和重传机制来保证可靠传输。
  • TCP 给数据分节进行排序,并使用累积确认保证数据的顺序不变和非重复。
  • TCP 使用滑动窗口机制来实现流量控制,通过动态改变窗口的大小进行拥塞控制。

TCP是相对可靠的传输层协议,它通过超时重传/滑动窗口等措施来保证它的字节流能够尽量可靠传输。

可靠传输的基本原理

TCP和UDP最基本的任务是将两个端系统间IP的数据交互扩展为运行在端系统的两个进程间的数据交互(即进程间的通信)这个过程称为传输层的多路复用多路分解,即网络通信中的端口通信。

在实际传输过程中,一连串的比特位(分组报文)会受到种种干扰从而有可能导致比特数据流的数据丢失。所以在传输分组报文层次上采用校验和技术来实现对分组数据的正确性校验。同时目的端接收到这个分组的时候会进行反馈(确认/否定确认)来告知发送端这个分组是不是正确收到了,假如正确收到了就继续发送,不正确就重发。而在发送端在一定时间内没接收到这个分组反馈就会超时重传(这时候可能导致接收端获得冗余副本)。

一系列的有序分组一个接一个的向目的传输,每个分组都等到上一个的确认再进行传输是一种简单流水线式的可靠传输实现。这种实现称为等停协议。但是它的传输效率十分低下,所以我们用滑动窗口协议(回退N步)和选择重传来实现一种更为高效的流水线数据传输。原理上就是允许发送端一次性发送一个指定范围内序号的分组但不需要立即确认当一个分组获得反馈后这个范围就依序继续向后滑动,这个范围就称作滑动窗口。

三次握手(建立链接)与四次挥手(断开链接)

所谓三次握手(Three-way Handshake),是指建立一个 TCP 连接时,需要客户端和服务器总共发送3个包。

三次握手的目的是连接服务器指定端口,建立 TCP 连接,并同步连接双方的序列号和确认号,交换 TCP 窗口大小信息。在 socket 编程中,客户端执行connect()时,将触发三次握手。

TCP 的连接的断开需要发送四个包,因此称为四次挥手(Four-way handshake),也叫做改进的三次握手。客户端或服务器均可主动发起挥手动作,在 socket 编程中,任何一方执行close()操作即可产生挥手操作。

UDP协议

UDP 是一个简单的传输层协议,和 TCP 相比UDP 有下面几个显著特性:

  • UDP 缺乏可靠性。UDP 本身不提供确认,序列号,超时重传等机制。UDP 数据报可能在网络中被复制,被重新排序。即 UDP 不保证数据报会到达其最终目的地,也不保证各个数据报的先后顺序,也不保证每个数据报只到达一次。
  • UDP 数据报是有长度的。每个 UDP 数据报都有长度,如果一个数据报正确地到达目的地,那么该数据报的长度将随数据一起传递给接收方。而 TCP 是一个字节流协议,没有任何(协议上的)记录边界。
  • UDP 是无连接的。UDP 客户和服务器之前不必存在长期的关系。UDP 发送数据报之前也不需要经过握手创建连接的过程。
  • UDP 支持多播和广播。
iOS中socket客户端
  • BSD Socket:BSD Socket 是UNIX系统中通用的网络接口,它不仅支持各种不同的网络类型,而且也是一种内部进程之间的通信机制。而iOS系统其实本质就是UNIX,所以可以用,但是比较复杂。
  • CFSocket:CFSocket是苹果提供给我们的使用Socket的方式(比较复杂)
  • AsyncSocket:第三方开源库(简单易用)。
AsyncSocket的简单使用
#import "GCDAsyncSocket.h"

@interface ViewController () <GCDAsyncSocketDelegate>
@property (nonatomic, strong) GCDAsyncSocket *clientSockfd;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    // 创建 Socket,在主队列中处理,所有的回执都在主队列中执行。
    self.clientSockfd = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
    [self.clientSockfd connectToHost:"127.0.0.1" onPort:8888 error:NULL];
}

#pragma mark - GCDAsyncSocketDelegate 协议方法

// 连接成功,协议方法
- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port {
    // 读取数据,必须添加,相当于主动添加一个读取请求,不然不会执行读取信息回调方法
    [self.clientSockfd readDataWithTimeout:-1 tag:0];

}

// 已经断开链接,协议方法
- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err {

}

// 读取到数据,协议方法
- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag {
    // 注意:要想长连接,必须还要在 DidReceiveData 的 delegate 中再写一次 [_udpSocket receiveOnce:&error]
    // 读取数据,读取完信息后,重新向队列中添加一个读取请求,不然当收到信息后不会执行读取回调方法。
    [self.clientSockfd readDataWithTimeout:-1 tag:0];

}

results matching ""

    No results matching ""