首页 > 技术文章 > 网络干货

cleven 2016-04-27 00:09 原文

 

一、OSI七层模型

  OSI七层模型(五层):本质:每一层都与很多的网络协议

(1) 应用层  :最接近用户,将应用程序呈现给用户,HTTP,FTP,POP3,SMTP,telnet ,DHCP 

(2)表示层  :解决不同系统间的通信

(3)会话层  :建立和管理应用程序间的通信

(4)传输层  : 建立端口间通信, TCP(三次握手),UDP(不可靠)

(5)网络层  : 建立主机间的通信,IP

(6)数据链路层 :确定数据的分组和解读方式,提供错误检测,形成、拆分数据帧,以太网协议,ARP

(7)物理层 : 确定物理接口、传输电信号(1、0的高低电平)

  

二、socket

1、是什么

(1)用于网络设备间应用程序数据通信的基本模型,封装了进程端口号和主机地址。是TCP/IP协议的抽象,为上层协议提供接口。

(2)本身不是协议,通过socket我们才能使用TCP/IP,socket是一组接口。

(3)socket 是基于传输层和应用层间的抽象层(5层模型)

2、怎么用

(1)在http请求中,已经集成了socket的一种应用。

(2)建立一条双向的通信需要两个socket

(3)OC没有对socket进行单独封装,使用流程:

   <1> 创建客户端Socket(网络地址类型、端口、传输协议)

   <2> 创建服务器Socket (服务端地址、端口、地址类型)       

   <3> 连接到服务器(客户端socket、服务端socket、服务端socket长度)    

   <4> 发送数据给服务器(发送内容地址、长度,客户端socket)

       <5> 接收服务器返回的数据 (客户端socket、接收缓存区、缓存区长度、接收方式)       

       <6> 关闭 Socket      

   

 

3、扩充

(1)socket编程

  socket编程是利用socket接口为应用层自定协议用于应用进程的网路通信。那为什么要自定义呢,自定义目的是满足自己的应用需求。例如http协议是应用层使用最多最广泛的协议,http是单工阻塞性质的协议,如果你需要一个全双工,无阻塞的双向传输,那http就满足不了。http定义自己的包头,你要是觉得传输效率极其重要,这样的包头太臃肿,你也需要自定义协议。自定义应用层协议就需要socket编程,目前应用的场景有,即时通讯,社交订阅更新,视频会议,网络游戏,股票基金实时价格等等。

 

(2)系统调用(system call)和应用程序接口(API)的概念。

  系统调用就是应用程序和操作系统之间传递控制权。当应用程序启动系统调用时,就把控制权从应用程序传递给系统调用接口,此接口又把控制权传递给操作系统,操作系统执行内部的操作,执行完毕控制权又通过系统调用返回给应用程序。这个系统调用接口就是API。API定义了很多系统调用的函数,通过请求调用就可以获得操作系统的服务。目前最著名就是伯克利为UNIX定义的socket interface。(层)

       回到网络中,传输层TCP协议和网络层的IP协议已经集成到操作系统中,应用程序在应用层,这就涉及到应用进程与操作系统的调用,而socket interface就作为应用进程和运输层协议之间的接口。因此,应用进程要使用TCP/IP协议进行通信就必须通过socket和操作系统进行调用请求服务。Socket把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。

 

(3)socket起源的理解

         socket起源于Unix,而Unix/Linux基本哲学之一就是“一切皆文件”,都可以用“打开open –> 读写write/read –> 关闭close”模式来操作。socket是可以理解为一种特殊的文件,socket函数就是对其进行的操作(读/写IO、打开、关闭)。

 

 

三、TCP/IP

 

1、TCP的三次握手和四次分手

(1)握手: 一个完整的三次握手: 请求(SYN)---应答(ACK +SYN)---再次确认(ACK+1)

    第一次握手:建立连接时,客户端A发送SYN包(SYN=j)到服务器B,并进入SYN_SEND状态,等待服务器B确认。 【A向B请求连接】

  第二次握手:服务器B收到SYN包,必须确认客户A的SYN(ACK=j+1),同时自己也发送一个SYN包(SYN=k),即SYN+ACK包,此时服务器B进入SYN_RECV状态。 【B回应A:好的,你来吧】

  第三次握手:客户端A收到服务器B的SYN+ACK包,向服务器B发送确认包ACK(ACK=k+1),此包发送完毕,客户端A和服务器B进入ESTABLISHED状态,完成三次握手。 【A回应B:好的,我来也】

 

(2)分手:一个完整的四次分手:A请求(FIN)--- B应答(ACK)---B关闭(FIN)---A应答(ACK)

由于TCP连接是全双工的,因此每个方向都必须单独进行关闭。这个原则是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向的连接。收到一个 FIN只意味着这一方向上没有数据流动,一个TCP连接在收到一个FIN后仍能发送数据。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。

  <1>客户端A发送一个FIN,用来关闭客户A到服务器B的数据传送。【A对B说:我传完了】 

  <2>服务器B收到这个FIN,它发回一个ACK,确认序号为收到的序号加1(报文段5)。和SYN一样,一个FIN将占用一个序号。 【B回应A:好的】

  <3>服务器B关闭与客户端A的连接,发送一个FIN给客户端A。 【B对A说:我传完了too】

  <4>客户端A发回ACK报文确认,并将确认序号设置为收到序号加1。 【A回应B:好的,我走了】

2、为什么三次握手却有四次分手?

  总结:连接时SYN和ACK可以放在一个报文中,但是分手时,由于连接是双向的,需要单独关闭每个方向上的数据传输,也就是单方向上的请求关闭和确认,FIN和ACK一般是分开发送的。

  这是因为服务端的LISTEN状态下的SOCKET当收到SYN报文的建连请求后,它可以把ACK和SYN(ACK起应答作用,而SYN起同步作用)放在一个报文里来发送。但关闭连接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了;但未必你所有的数据都全部发送给对方了,所以你可以未必会马上会关闭SOCKET,也即你可能还需要发送一些数据给对方之后,再发送FIN报文给对方来表示你同意现在可以关闭连接了,所以它这里的ACK报文和FIN报文多数情况下都是分开发送的.

3、为什么用三次握手

(1)为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误

(2) 还有一种说法是为了解决“网络中存在延迟的重复分组”的问题。

 

 

四、HTTP

1、是什么以及干什么用的

(1)超文本传输协议,目前1.1版本

(2)基于应用层的通信规范,规定客户端和服务器之间的数据传输格式

(3)iOS网络开发中,多用于进行发送HTTP请求

 

2、特点

(1)短连接,无状态连接(每次新建连接),通过TCP完成数据请求后立即释放。

 

(2)Keep-Alive 心跳包(1.1版本正式提供):

 

     <0>如果客户端浏览器支持Keep-Alive,那么就在HTTP请求头中添加一个字段 Connection: Keep-Alive,服务器收到请求时,会在响应头中添加一个同样的字段来使用Keep-Alive。客户端和服务器之间的HTTP连接就会被保持,不会断开,直到超时会或意外断开。

     <1> 为了提高效率,使用心跳包,使得TCP短暂保持连接

     <2> 时间可以设定,过期后仍然断开连接,所以HTTP还是短连接 

     <3>使用session, Cookie等技术,也能保持用户的状态,但是每一次连接依然是无状态连接

 

(3)有请求才有回应,不请求不回应

 

(4)HTTP允许传输任意类型的数据

 

(5)简单快速,因为HTTP协议简单,所以HTTP服务器的程序规模小,因而通信速度很快

 

(6)采用短连接,一个连接处理一个请求,缩短数据请求和传输时间(0.9和1.0的特性,没有开启心跳包时)

 

3、OC中怎么使用

(1)使用http协议发送网络请求,http请求可以理解为特殊处理的socket

(2)HTTP请求格式:

   <1>请求行:  GET(请求方法) /resources/vedios.json(资源路径) HTTP/1.1(http协议版本)

 

   <2>请求头:  User-Agent (告诉服务器的一些数据)

        其他头信息:

        Accept: text/html       // 客户端所能接收的数据类型

        Accept-Language: zh-cn // 客户端的语言环境

        Accept-Encoding: gzip // 客户端支持的数据压缩格式

        Host: m.baidu.com       // 客户端想访问的服务器主机地址

        User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:37.0) Gecko/20100101 Firefox/37.0 // 客户端的类型,客户端的软件环境

 

 

     <3> 请求体:  只有 POST 请求才有请求体 ,GET 请求是没有请求体的.

 

(3)http响应格式

 

   <1>响应行(状态行): HTTP/1.1(http协议版本) 304(网络连接状态码) Not Modified(网络连接状态码简要说明)

 

   <2>响应头: 会返回服务器信息,还会返回本次请求数据(实体内容)的信息。

 

      其他头信息:

        Content-Encoding: gzip     // 服务器支持的数据压缩格式

        Content-Length:  1528          // 返回数据的长度

        Content-Type:  application/xhtml+xml;charset=utf-8 // 返回数据的类型

        Date: Mon, 15 Jun 2015 09:06:46 GMT             // 响应的时间

        Server: apache                           // 服务器类型

 

   <3>实体内容: 就是客户端想要的数据。

  

(4)http请求方法

  <1>OC中没有针对HTTP请求格式做好的封装类,我们要手动封装

  <2>请求方法(不区分大小写):GET、POST、OPTIONS、HEAD、PUT、DELETE、TRACE、CONNECT、PATCH 只用前两个

(tip:put操作是幂等性的,即重复操作只执行一个结果,而post不是。

put的创建操作针对的是具体资源,及带有文件名的路径,而post不是,只要集合名就可以)

 

(5)发送http请求的工具

  <1>苹果原生:

      * NSURLConnection:用法简单,古老经典的一种方案.

      * NSURLSession:iOS7以后推出的技术,功能比NSURLConnection更加强大

    * CFNetWork:NSURL 的底层,纯C语言,一般不用.

      <2>第三方框架:

      * ASIHttpRequest:http终结者,功能很强大,可惜作者已停止更新,2012年停止更新。可惜。。。

      * AFNetWorking:简单易用,提供了基本够用的常用功能,维护和使用者多.

      * MKNetWorkKit:简单易用,产自印度,维护和使用者少.

 

4、关于http短连接和socket长连接补充

  Http是在每次请求完成后就把TCP连接关了,所以是短连接。直接通过Socket编程使用TCP协议的时候,因为我们自己可以通过代码去控制什么时候打开连接什么时候关闭连接,只要我们不通过代码把连接关闭,这个连接就会在客户端和服务端的进程中一直存在,相关状态数据会一直保存着。

 

 

5、常用请求方式get、post、head

 

(1) GET

   <1>用于一般的网络请求,请求参数封装在url后面,例  http://127.0.0.1/login?username=zhangqi&password=12345

   <2>参数长度有限制(一般2~8K)、速度快、不安全、会做本地缓存(保存在SQLite的数据库中(路  径:NSHomeDirectory()))。

  <3>NSURLRequest默认使用GET请求。

 

(2) POST

  <1>可以做一般网络请求,也可以请求大数据,或者做数据上传。

  <2>需要设置设置 NSURLRequest 的 HTTPMethod、HTTPBody属性

  <3>没有长度限制、安全低效、私密信息必须使用POST、不做本地缓存

 

(3) HEAD请求方法

  <1>只获取响应头信息,不获取具体的数据内容.响应头中有我吗需要的内容,比如文件类型字段。

  <2>一般 HEAD 请求都使用同步的方法发送.因为不获取实体内容,返回的数据只有响应头信息.

  <3>request.HTTPMethod = @"HEAD"

  

6、RESTful设计风格

 

主要用于后端开发,主要的表现形式为使用同一个 URL,不同的 HTTP 访问方法,表达不同的语义。

 

 

7、网络连接状态码

 (1)1xx消息

      代表请求已被接受,需要继续处理。这类响应是临时响应,只包含状态行和某些可选的响应头信息,并以空行结束。除非在某些试验条件下,服务器禁止向此类客户端发送1xx响应。

 (2)2xx成功

      代表请求已成功被服务器接收、理解、并接受。例:200 OK:请求已成功,请求所希望的响应头或数据体将随此响应返回。202 Accepted服务器已接受请求,但尚未处理。

 (3)3xx重定向

      代表需要客户端采取进一步的操作才能完成请求。

 (4)4xx客户端错误

      代表了客户端看起来可能发生了错误,妨碍了服务器的处理。除非响应的是一个HEAD请求,否则服务器就应该返回一个解释当前错误状况的实体,以及这是临时的还是永久性的状况。例:404 Not Found :请求失败,请求所希望得到的资源未被在服务器上发现。408 Request Timeout请求超时。400 Bad Request 由于包含语法错误,当前请求无法被服务器理解。

 (5)5xx服务器错误

      代表了服务器在处理请求的过程中有错误或者异常状态发生,也有可能是服务器意识到以当前的软硬件资源无法完成对请求的处理。

  

 8、网络操作补充

(1)获取本地文件大小(先得到属性字典,但是得不到文件类型

[NSFileManager defaultManager] attributesOfItemAtPath:@“本地地址”

 

(2)如何获取服务器文件大小/类型

通过发送head请求,得到NSResponse其中的属性:expectedContentLength /MIMEType

 

(3)句柄操作:NSFileHandle

文件操纵句柄,操纵的是文件内部,依赖于文件。 如果文件路径下没有这个文件,文件操纵句柄不会实例化成功。

 

(4)输出管道流:NSOutputStream

如果文件路径下没有这个文件,会自动创建一个文件

 

 

五、AFN

1 、AFN的概念原理:

(1)AFN的基础是NSURL

(2)AFN的直接操作对象AFHTTPClient是一个实现了NSCoding和NSCopying协议的NSObject子类。

(3)AFHTTPClient是一个封装了一系列操作方法的“工具类”,处理请求的操作类是一系列单独的,基于NSOperation封装的,AFURLConnectionOperation的子类。AFN的示例代码中通过一个静态方法,使用dispatch_once()的方式创建AFHTTPClient的共享实例,这也是官方建议的使用方法。在创建AFHTTPClient的初始化方法中,创建了OperationQueue并设置一系列参数默认值。在getPath:parameters:success:failure方法中创建NSURLRequest,以NSURLRequest对象实例作为参数,创建一个NSOperation,并加入在初始化发方中创建的NSOperationQueue。以上操作都是在主线程中完成的。

 

2、更新

AFNetworking3.0删除了了对 NSURLConnection的封装内容

3、支持后台运行的网络任务

  •    暂停、停止、重启网络任务,不需要自己封装NSOperation
  •    支持断点续传,异步下载
  •    支持上传(单文件上传),异步上传
  •    获取下载、上传的进度

 

4、 AFN与其它框架对比

(1) AFNetWorking:简单易用,提供了基本够用的常用功能,有人更新和维护,而且目前使用者很多 。其相关资料,文档,demo很多,很好找遇到问题好解决。

(2)ASIHttpRequest:

  <1>ASI的底层基于纯C语言的CFNetwork框架,功能很强大,可惜作者已停止更新.

  <2>ASI 能够同时实现上传多个文件

  <3>MRC的,2012年就停止更新了,设计的目标平台:iOS 2.0/iOS 3.0 。之前的组合 ASI+SBJSON。

(3) MKNetWorkKit:简单易用,维护和使用者少.

 

5、AFN的数据解析,服务器返回的数据必须和解析器相对应。

 

(1)特点:  可以自动对服务器返回的数据进行解析,默认将服务器返回的数据当做 JSON 数据解析.

(2)AFN解析器的概念:

   <1>当做是JSON来解析(默认做法),成功返回的responseObject的类型是NSDictionary或者NSArray。

   mgr.responseSerializer = [AFJSONResponseSerializer serializer];

   <2> 当做是XML来解析,responseObject的类型是NSXMLParser

   mgr.responseSerializer = [AFXMLParserResponseSerializer serializer];  

     <3> 直接返回data,不要去解析服务器返回的数据,保持原来的data即可,对于文件/图片/视频/网页HTML,只能选择万能解析器!

     mgr.responseSerializer = [AFHTTPResponseSerializer serializer];

 

(3)解析器的一种特殊更改方式

   <1> 当前 manager 解析器默认将所有数据当做 JSON 数据解析。

   <2> 此时服务器传回的数据是 内容是JSON格式,但是文件没有后缀名,默认为text/plain 类型,不是JSON类型。

   <3> 不更改解析器类型的情况下,可以有两种方式同样实现解析:

     (1)更改框架,去JSON解析器的初始化方法中,更改acceptableContentTypes里面的内容。

     (2)不更改框架,给默认解析器的acceptableContentTypes属性重新赋值:

     manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript" ,@"text/plain",nil];

  

 

6、使用AFNetworkReachabilityManager,检测网络状态

(1)操作步骤 

   <1> 实例化网络工具监测类.

      AFNetworkReachabilityManager *manager = [AFNetworkReachabilityManager sharedManager];

     <2> 设置网络状态改变之后的操作.

  // ReachabilityStatusChangeBlock:一旦网络状态改变之后,就会执行下面的 block.

   // status : 枚举值,代表当前的网络状态

   [manager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {

    }];

      <3> 开启网络监测

  [manager startMonitoring];

    

    

7、使用 AFN中的 AFSecurityPolicy :安全策略,支持 HTTPS 请求(跳过验证的步骤!)

(1)AFN3.0之前,让 AFN 支持 HTTPS 

    manager.securityPolicy.allowInvalidCertificates = YES;

(2)AFN3.0之后,让 AFN 支持 HTTPS 

    manager.securityPolicy.validatesDomainName = NO;

 

8、比较汇总

 

        

 

 

 

六、XML数据解析

1、SAX解析:

(1)NSXMLParser的代理

(2)逐行解析

 

2、DOM解析:

(1)三方框架GDataXML

(2)一次加载整个XML文档      

(3)几个词:根元素rootElement、子元素children、元素GDataXMLElement、属性attributes、节点GDataXMLNode、内容

(4)节点的属性:stringValue、name

     

 

 

七、NSURLConnection 和 NSURLSession的区别

 

1、前者以在iOS9.0已经被废弃

2、前者可以在初始化时确定发送同步还是异步的请求,并且可以选择执行队列。而后者只能异步发送网络请求。

3、使用方式(实例化)不同

(1)前者有类方法,可以不用实例化直接发送同步或异步请求。

(2)后者有单例对象,也可自定义对象。

 

4、网络任务的概念

NSURLSection 有网络任务的概念:task ,三种不同的网络任务(普通,上传,下载)

 

5、关于请求的启动

NSURLSection 默认实例化网络任务后,是挂起的,需要resume

 

6、使用场景:

 

(1) 普通的网络任务:服务器返回的是 JSON/XML/HTML 等数据量比较小. 与 NSUrlConnection 的异步网络请求没有任何区别!

(2) 文件上传: 默认NSUrlSession 的文件上传走的是 PUT 请求.文件上传跟 NSUrlConnection 也基本没有区别.

(3) 文件下载: 如果服务器返回的是一些比较大的数据,NSUrlSession 的下载做的是最好的,封装的非常全面

 

7、关于下载“大文件”时的不同

 

(1) NSUrlConnection 使用dataDelegate监控下载进度,需要配合NSFileHandle 或者 NSOutputStream(文件不存在可以创建)进行数据的存储。

    NSUrlSession 下载使用自己的方法(生成downloadTask,然后resume)

     (代理方法监测下载进度)

 

(2)NSURLSession下载完成后,会删除内容(temp文件夹中的文件)

 

8、关于断点续传的不同

(1)NSUrlConntection 需要使用代理方法,同时,设置请求头的rang属性

(2)通过暂停或取消,生成resumeData,需要续传时,根据resumeData生成新任务。

 

 

 

推荐阅读