首页 > 代码库 > 作为一个iOS攻城狮不得不了解的网络知识

作为一个iOS攻城狮不得不了解的网络知识

1.前言:

最为一个iOS开发工程师,不论实在面试时候还是在与服务器人员讨论网络请求相关知识时候都需要具备基础的常识,比如说:OSI、HTTP、HTTP和HTTPS的区别,以及2016年6月1日起苹果APP审核新增内容的IPV6相关知识。在此小编也几乎是从零学起了

2.什么是OSI

我们所说的OSI全名是:开放式系统互联通信参考模型(Open System Interconnection Reference Model),简称OSI模型;首先要了解的是它是一种概念模型,由国际标准化组织(ISO)提出,一个试图使各种计算机在世界范围内互连为网络的标准框架。

OSI将计算机网络体系结构划分为以下七层,如下图所示:

技术分享

(图片来源于维基百科)


第7层 应用层(Application Layer)

提供为应用软件而设的界面,以设置与另一应用软件之间的通信。例如: HTTP,HTTPS,FTP,TELNET,SSH,SMTP,POP3等。

第6层 表示层(Presentation Layer)

把数据转换为能与接收者的系统格式兼容并适合传输的格式。

第5层 会话层(Session Layer)

负责在数据传输中设置和维护电脑网络中两台电脑之间的通信连接。

第4层 传输层(Transport Layer)

把传输表头(TH)加至数据以形成数据包。传输表头包含了所使用的协议等发送信息。例如:传输控制协议义(TCP) 等。

第3层 网络层(Network Layer)

决定数据的路径选择和转寄,将网络表头(NH)加至数据包,以形成分组。网络表头包含了网络数据。例如:互联网协议(IP) 等。

第2层 数据链接层(Data Link Layer)

负责网络寻址、错误侦测和改错。当表头和表尾被加至数据包时,会形成了帧。数据链表头(DLH)是包含了物理地址和错误侦测及改错的方法。数据链表尾(DLT)是一串指示数据包末端的字符串。例如以太网、无线局域网(Wi-Fi)和通用分组无线服务(GPRS)等。分为两种子层:logic link control sublayer & media access control sublayer

第1层 物理层(Physical Layer)

在局部局域网上传送帧,它负责管理电脑通信设备和网络媒体之间的互通。包括了针脚、电压、线缆规范、集线器、中继器、网卡、主机适配器等


3.什么是HTTP

超文本传输协议英文HyperText Transfer Protocol缩写HTTP)是互联网上应用最为广泛的一种网络协议是一个客户端终端(用户)和服务器端(网站)请求和应答的标准(TCP)。

发出的请求信息包括以下几个:

  • 请求行
     例如GET /images/logo.gif HTTP/1.1,表示从/images目录下请求logo.gif这个文件。
  • (请求)头
    例如Accept-Language: en
  • 空行
  • 其他消息体

请求行和标题必须以<CR><LF>作为结尾。空行内必须只有<CR><LF>而无其他空格。在HTTP/1.1协议中,所有的请求头,除Host外,都是可选的。

HTTP/1.1协议中共定义了八种方法(也叫“动作”)来以不同方式操作指定的资源:

  • OPTIONS:这个方法可使服务器传回该资源所支持的所有HTTP请求方法。用‘*‘来代替资源名称,向Web服务器发送OPTIONS请求,可以测试服务器功能是否正常运作。
  • HEAD与GET方法一样,都是向服务器发出指定资源的请求。只不过服务器将不传回资源的本文部分。它的好处在于,使用这个方法可以在不必传输全部内容的情况下,就可以获取其中“关于该资源的信息”(元信息或称元数据)
  • GET向指定的资源发出“显示”请求。使用GET方法应该只用在读取数据,而不应当被用于产生“副作用”的操作中,例如在Web Application中。其中一个原因是GET可能会被网络蜘蛛等随意访问。参见安全方法
  • POST向指定资源提交数据,请求服务器进行处理(例如提交表单或者上传文件)。数据被包含在请求本文中。这个请求可能会创建新的资源或修改现有资源,或二者皆有。
  • PUT向指定资源位置上传其最新内容。
  • DELETE请求服务器删除Request-URI所标识的资源。
  • TRACE回显服务器收到的请求,主要用于测试或诊断。
  • CONNECTHTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。通常用于SSL加密服务器的链接(经由非加密的HTTP代理服务器)。

方法名称是区分大小写的。当某个请求所针对的资源不支持对应的请求方法的时候,服务器应当返回状态码405(Method Not Allowed),当服务器不认识或者不支持对应的请求方法的时候,应当返回状态码501(Not Implemented)。

HTTP服务器至少应该实现GET和HEAD方法,其他方法都是可选的。当然,所有的方法支持的实现都应当匹配下述的方法各自的语义定义。此外,除了上述方法,特定的HTTP服务器还能够扩展自定义的方法。

状态码

所有HTTP响应的第一行都是状态行,依次是当前HTTP版本号,3位数字组成的状态代码,以及描述状态的短语,彼此由空格分隔。

状态代码的第一个数字代表当前响应的类型:

  • 1xx消息——请求已被服务器接收,继续处理
  • 2xx成功——请求已成功被服务器接收、理解、并接受
  • 3xx重定向——需要后续操作才能完成这一请求
  • 4xx请求错误——请求含有词法错误或者无法被执行
  • 5xx服务器错误——服务器在处理某个正确请求时发生错误

4.HTTP与HTTPS的区别

https超文本传输安全协议,Hypertext Transfer Protocol Secure缩写HTTPS。计算机网络上,HTTPS经由超文本传输协议进行通信,但利用SSL/TLS来对数据包进行加密。HTTPS开发的主要目的,是提供对网络服务器的身份认证,保护交换数据的隐私与完整性

5.ipv6

与HTTP的差异

HTTPURL由“http://”起始且默认使用端口80不同,HTTPS的URL由“https://”起始且默认使用端口443。

HTTP是不安全的,且攻击者通过监听中间人攻击等手段,可以获取网站帐户和敏感信息等。HTTPS被设计为可防止前述攻击,并(在没有使用旧版本的SSL时)被认为是安全的。

协议层

HTTP协议和安全协议同属于应用层(OSI模型的最高层),具体来讲,安全协议工作在HTTP之下,运输层之上:安全协议向运行HTTP的进程提供一个类似于TCP的套接字,供进程向其中注入报文,安全协议将报文加密并注入运输层套接字;或是从运输层获取加密报文,解密后交给对应的进程。严格地讲,HTTPS并不是一个单独的协议,而是对工作在一加密连接(TLS或SSL)上的常规HTTP协议的称呼。

HTTPS报文中的任何东西都被加密,包括所有报头和荷载。除了可能的选择密文攻击(参见限制小节)之外,一个攻击者所能知道的只有在两者之间有一连接这一事实。

服务器设置

要使一网络服务器准备好接受HTTPS连接,管理员必须创建一数字证书,并交由证书颁发机构签名以使浏览器接受。证书颁发机构会验证数字证书持有人和其声明的为同一人。浏览器通常都预装了证书颁发机构的证书,所以他们可以验证该签名。

获得证书

由证书颁发机构签发的证书有免费的,也有每年收费数美元到数千美元不等的。

一个组织也可能有自己的证书颁发机构,尤其是当设置浏览器来访问他们自己的网站时(如,运行在公司或学校局域网内的网站)。他们可以容易地将自己的证书加入浏览器中

作为访问控制

HTTPS也可被用作客户端认证手段来将一些信息限制给合法的用户。要做到这样,管理员通常会给每个用户创建证书(通常包含了用户的名字和电子邮件地址)。这个证书会被放置在浏览器中,并在每次连接到服务器时由服务器检查。

当私钥失密时

证书可在其过期前被吊销,通常情况是该证书的私钥已经失密。较新的浏览器如Google ChromeFirefox[6]Opera[7]和运行在Windows Vista上的Internet Explorer[8]都实现了在线证书状态协议(OCSP)以排除这种情形:浏览器将网站提供的证书的序列号通过OCSP发送给证书颁发机构,后者会告诉浏览器证书是否还是有效的。

局限

TLS有两种策略:简单策略和交互策略。交互策略更为安全,但需要用户在他们的浏览器中安装个人的证书来进行认证

不管使用了哪种策略,协议所能提供的保护总强烈地依赖于浏览器的实现和服务器软件所支持的加密算法

HTTPS并不能防止站点被网络蜘蛛抓取。在某些情形中,被加密资源的URL可仅通过截获请求和响应的大小推得,这就可使攻击者同时知道明文(公开的静态内容)和密文(被加密过的明文),从而使选择密文攻击成为可能。

因为SSL在HTTP之下工作,对上层协议一无所知,所以SSL服务器只能为一个IP地址/端口组合提供一个证书。这就意味着在大部分情况下,使用HTTPS的同时支持基于名字的虚拟主机是不很现实的。一种叫域名指示(SNI)的方案通过在加密连接创建前向服务器发送主机名解决了这一问题。Firefox 2、Opera 8和运行在Windows VistaInternet Explorer 7都加入了对SNI的支持。

因为HTTPS连接所用的公钥以明文传输,因此中国大陆的防火长城可以对特定网站按照匹配的黑名单证书,通过伪装成对方向连接两端的计算机发送RST包干扰两台计算机间正常的TCP通讯,以打断与特定IP地址之间的443端口握手,或者直接使握手的数据包丢弃,导致握手失败,从而导致TLS连接失败。这也是一种互联网信息审查和屏蔽的技术手段。

如果Mac OS X中的家长控制被启用,那么HTTPS站点必须显式地在“总是允许”列表中列出。


互联网通信协议第6版英文Internet Protocol version 6缩写:IPv6)是互联网协议的最新版本,用于分组交换互联网络的网络层协议,旨在解决IPv4地址枯竭问题

与IPv4比较

在Internet上,数据以分组的形式传输。IPv6定义了一种新的分组格式,目的是为了最小化路由器处理的报文首部[5][6]。由于IPv4报文和IPv6报文首部有很大不同,因此这两种协议无法互操作。但是在大多数情况下,IPv6仅仅是对IPv4的一种保守扩展。除了嵌入了互联网地址的那些应用协议(如FTPNTPv3,新地址格式可能会与当前协议的语法冲突)以外,大多数传输层和应用层协议几乎不怎么需要修改就可以工作在IPv6上。


苹果于2016年6月1日开始对发布至苹果AppStore的应用增加对ipv6支持的审核,如果不支持则会因此被拒

目前用iOS设备连接Wifi、3/4G网络时,设备被分配地址皆为IPv4地址,但是随着运营商和企业逐渐部署IPv6 DNS64/NAT64网络之后,设备被分配的地址会变成IPv6地址,而这些网络称为IPv6-Only网络,且仍可以通过该网络去获取IPv4地址提供的内容。

客户端向服务器端请求域名解析,首先通过DNS64 Server查询IPv6的地址,如果查询不到,再向DNS Server查询IPv4地址,通过DNS64 Server合成一个IPv6的地址,最终将一个IPv6的地址返回给客户端。


6.Apple如何审核支持IPv6


关于最近越来越多的应用因ipv6的原因被拒,根据小编的经验提供以下建议:

首先,对于目前的iOS应用来说,绝大多数的网络交互部分都是采用的是AFNetWorking这个框架,有些事基于AFN的一些封装,如果你的应用因ipv6的缘故被拒,你首先要做的就是检查你的AFN版本,如果你是用cocoapod安装的话,就首先升级你的AFN版本,

在你的podfile里面添加代码:

source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'

target 'TargetName' do
pod 'AFNetworking', '~> 3.0'
end

建议升级的最新的版本,3.1.0,更新时间2016年10月11日,只要安装AFN版本大于3.0即可,

如果你是手动导入的,那么就需要去GitHub上下载最新版本的框架,

下载地址:https://github.com/AFNetworking/AFNetworking


最新版本的AFN与之前版本的区别:

在AFNetworking 3.0之前,底层是通过封装NSURLConnection来实现的。 
在AFNetworking 3.0之后,也就是在iOS 9.0 之后,NSURLConnection被弃用,苹果推荐使用NSURLSession来管理网络请求,所以AFNetworking 3.0之后,底层是通过封装NSURLSession来实现的。


从AFNetworking 3.0中之后,下面三个方法被弃用了。

AFURLConnectionOperation
AFHTTPRequestOperation
AFHTTPRequestOperationManager
依次被下面三个类代替了,同时请求方法也跟着改变了,所以AFNetworking 3.0以后发生了很大的变化。


AFURLSessionManager
AFHTTPSessionManager
AFNetworkReachabilityManager


了解之后,去你的项目里面把过期的方法替换为最新的方法,代码如下:

1.PUT请求:
AFHTTPSessionManager* manager = [AFHTTPSessionManager manager];
    manager.requestSerializer.timeoutInterval = 10;

    [manager PUT:@"你得API地址" parameters:params success:^(NSURLSessionDataTask* _Nonnull task, id _Nullable responseObject) {
        NSLog(@"service request success");
        
        completion();
    }
        failure:^(NSURLSessionDataTask* _Nullable task, NSError* _Nonnull error) {
           
            ALERT_MESSAGE([self resolveWithError:error]);
            
            errorBlock();
        }];
2.GET请求:
AFHTTPSessionManager* manager = [AFHTTPSessionManager manager];
    manager.requestSerializer.timeoutInterval = TIME_OUT_INTERVAL;

   
    [manager GET:API parameters:params progress:nil success:^(NSURLSessionDataTask* _Nonnull task, id _Nullable responseObject) {
       
        completion();
    }
        failure:^(NSURLSessionDataTask* _Nullable task, NSError* _Nonnull error) {
            errorBlock([self resolveWithError:error]);
        }];

3.POST请求(如果不是上传数据,尽量不要用带请求体的POST方法)
AFHTTPSessionManager* manager = [AFHTTPSessionManager manager];
    manager.requestSerializer.timeoutInterval = TIME_OUT_INTERVAL;
    manager.responseSerializer = [AFHTTPResponseSerializer serializer];
    manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"text/plain", @"text/json", @"application/json", @"text/javascript", @"text/html", nil];

    

    [manager POST:REGISTER_POST_API parameters:params progress:^(NSProgress* _Nonnull uploadProgress) {

    }
        success:^(NSURLSessionDataTask* _Nonnull task, id _Nullable responseObject) {
            completion();

        }
        failure:^(NSURLSessionDataTask* _Nullable task, NSError* _Nonnull error) {
            SHOW_ERROR_MESSAGE([self resolveWithError:error]);

        }];


如果项目中使用有Reachability检测网络的话也需要升级到较新的版本,


Apple要支持的IPv6其实是某些特定网络,通常称之为IPv6-Only,就是说让App在 IPv6 DNS64/NAT64 网络环境下仍然能够正常运行。当前环境下,实际网络环境还是IPv4网络,也就要求App需要能够同时保证IPv4和IPv6网络环境下的可用性。


从这点来说,苹果不会去扫描IPv4的专有API来拒绝审核通过,因为IPv4的API和IPv6的API调用都会同时存在于代码中。从这点看,最近被拒的App苹果不是通过IPv4的专有API接口扫描拒绝的。

Apple官方声明:iOS 9开始向IPv6支持过渡,在iOS 9.2支持IPv4地址合成IPv6地址,其提供的Reachability库在iOS 8系统下,当从IPv4切换到IPv6网络,或者从IPv6网络切换到IPv4,是无法监控到网络状态的变化。也有一些开发者针对这些Bug询问Apple的审核部门,给予的答复是只需要在苹果最新的系统上保证IPv6的兼容性即可。
当下要解决的是App的主流程支持IPv6,通过苹果审核即可。对于某些不支持IPv6的模块,可以暂时不用添加;考虑到IPv6还有一个较长的过渡期,短时间内不会影响我们用户的正常使用。 

当下,那些模块需要支持IPv6


1. NSURLConnection

NSURLConnection在iOS9系统上是支持IPv6。


2. Reachability

Reachability可不做任何修改,在iOS 9上可以支持IPv6和IPv4两种网络环境,但是在iOS 9以下会存在bug,但是苹果审核时并不关心这点。


3. socket API

App中使用了长连接,其必然会使用底层socket API,socket API需要支持IPv4和IPv6。


4.本机 IP /设备网关地址/设备 DNS 地址/域名 DNS 地址获取都需要支持IPv6。


附:参考内容:

https://zh.wikipedia.org/wiki/OSI

https://zh.wikipedia.org/wiki/IPv6

https://zh.wikipedia.org/wiki/%E8%B6%85%E6%96%87%E6%9C%AC%E4%BC%A0%E8%BE%93%E5%8D%8F%E8%AE%AE

https://zh.wikipedia.org/wiki/%E8%B6%85%E6%96%87%E6%9C%AC%E4%BC%A0%E8%BE%93%E5%AE%89%E5%85%A8%E5%8D%8F%E8%AE%AE

http://www.gupowang.com/app/4465.html


作为一个iOS攻城狮不得不了解的网络知识