Onewang

iOS developer logging

生命不息,奋斗不止


主页

网络通信

计算机网络体系结构

计算机的网络体系结构 OSI 的七层协议体系结构的概念清晰,理论完整,当时它既复杂又不实用; TCP/IP 体系结构则不同,但是它现在却得到了非常广泛的应用,不过从实质上讲, TCP/IP 只是最上面的三层,因为最下面的网络接口层并没有什么具体内容;因此在学习计算机网络的时候往往采取折中的方法,即综合 OSI 和 TCP/IP 的优点,采用一种只有五层协议的体系结构;

  • 物理层:主要任务是将比特流与电子信号进行转换;确定与传输媒体的接口有关的一些特性;
  • 数据链路层:定义了通过通信介质相互连接的设备之间数据传输的规范(MAC 地址和分组交换);主要使用两种信道进行通信:点对点信道广播信道;主要解决三个问题:封装成帧,透明传输差错检测;
  • 网络层:主要作用是实现终端节点的通信(IP协议);IP 协议的三大作用: IP 寻址,路由和 IP 分包;网络层向上只提供简单灵活的,无连接的,尽最大努力交付的数据报服务;其实质就是不可靠的传输;
  • 传输层:传输层是向上面的应用层提供通信服务,它属于面向通信部分的最高层,但同时又是面向用户部分的最底层;其中最重要的两个传输协议是 面向无连接的UDP 和面向连接的 TCP;
  • 应用层:应用层的具体内容就是规定应用进程在通信时所遵循的协议;而每个应用层的协议都是为了解决某一类应用问题,而问题的解决又往往是通过位于不同主机中的多个应用进程之间的通信和协同工作来完成的;如: http, FTP 等;

iOS 开发中的网络通信主要是在传输层和应用层进行一些网络 IP 地址,端口以及协议的一些处理;首先是网络层的两种传输协议 UDP 和 TCP 的含义以及区别:

UDP

用户数据包协议;UDP 在传输数据之前不需要先建立连接.远地主机的运输层在收到 UDP 报文后,不需要给出任何确认; 主要特点:

  • UDP 是无连接的,即发送数据之前不需要简历连接,因此减少了开销和发送数据之前的时延;
  • UDP 使用尽最大努力交付,即不保证可靠交付,因此主机不需要维持复杂的连接状态表(这里面有很多参数);
  • UDP 是面向报文的;发送方的 UDP 对应用程序交下来的报文,在添加首部后就向下交付给 IP 层; UDP对应用层交下来的报文,既不合并,也不拆分,而是保留这些报文的边界;但是对于接受方的UDP来说,对 IP 层交上来的UDP用户数据报,除去首部后就原封不动的交付给上层的应用进程.报文过长或者过短, UDP把它交给IP 层后,IP 层在传送时可能要进行分片或者会使数据报的首部的相对长度太大,这都会降低 IP 层的效率;
  • UDP 没有拥塞控制,因此网络出现的拥塞不会使源主机的发送率降低;
  • UDP 支持一对一,一对多,多对一和多对多的交互通信;
  • UDP 的首部开销小,只有8字节,比 TCP 的20个字节的首部要短;

TCP

传输控制协议; TCP 提供面向连接的服务;在传输数据之前必须先建立连接,数据传输完成后要释放连接;建立连接需要通过三次握手,而释放连接需要四次握手; 主要特点:

  • TCP 是面向连接的传输层协议;
  • 每一条TCP连接之只能有两个端点,每条 TCP 连接只能是点对点的;
  • TCP 提供可靠交付的服务,也就是说,通过 TCP 连接传输的数据,无差错,不丢失,不重复,并且按序到达;
  • TCP 提供全双工通信;即允许通信双方的应用进程在任何时候都能发送数据;
  • 面向字节流;TCP 中的”流”指的是流入到进程或从进程流出的字节序列;”面向字节流”的含义就是虽然应用程序和 TCP 的交互式一次一个数据块,但 TCP 把应用程序交下来的数据看成仅仅是一连串的无结构的字节流;并不知道所传送字节流的含义;

###区别: udp和tcp的区别.png

TCP/IP协议

图解TCP:IP协议.jpg

TCP连接需要三次握手的过程

第一次握手:客户端发送syn包(seq=x)到服务器,并进入SYN_SEND状态,等待服务器确认; 第二次握手:服务器收到syn包,必须确认客户的SYN(ack=x+1),同时自己也发送一个SYN包(seq=y),即SYN+ACK包,此时服务器进入SYN_RECV状态; 第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=y+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。 握手过程中传送的包里不包含数据,三次握手完毕后,客户端与服务器才正式开始传送数据。理想状态下,TCP连接一旦建立,在通信双方中的任何一方主动关闭连接之前,TCP 连接都将被一直保持下去。

TCP连接为什么需要三次握手?

这个问题的本质就是信道不可靠,但是通信双方需要中间传输的数据是可靠的,而要解决这个问题,无论你是在信息中包含什么信息,三次通信是理论上的最小值,所以三次握手不是TCP本身的要求,而是为了满足在不可靠信道上可靠的传输信息这一需求所致的;这里的本质需求就是,信道不可靠,数据传输要可靠,三次握手之后你先继续握手还是发数据也好,跟进行可靠信息传输的需求就没关系了,因此如果信道可靠,无论什么时候发出消息,对方一定能收到,或者你不关心是否要保证对方收到你的消息,那就能像UDP那样直接发送消息就可以;

  • 二次握手的情况:客户端给服务器发送建立连接的请求,服务器同意连接请求发回应给客户端,连接就此建立; 问题是在网络中经常出现包的延迟,如果客户端的某个包在路由上延迟了,过了很久才发给服务器,服务器收到这个包后回应给客户端,服务器以为连接就此建立成功,分配资源,这样就会出现问题;
  • 四次握手的会浪费资源;
  • 三次握手目的是为了防止已失效的连接请求报文段突然又传到服务端,因而产生错误;为了解决网络中存在延迟的重复分组的问题
为什么TCP协议终止链接需要四次?

1.当主机A确认发送完数据且知道B已经接受完了,想要关闭发送数据接口(当然确认信号还是可以发),就会发FIN给主机B; 2.主机B收到A发送的FIN,表示收到了,就会发送ACK回复; 3.但是这时B可能还在发送数据,没有想要关闭数据口的意思,所以FIN和ACK不是同时发送的,而是等到B数据发送完,才会发送FIN给主机A; 4.A收到B发来的FIN,知道B的数据也发送完了,回复ACK,A等待2MSL以后,没有收到B传来的任何消息,知道B已经收到自己的ACK了,A就关闭链接,B也关闭链接;

A为什么等待2MSL,从TIME_WAIT到CLOSE?

在客户端发送最后的ACK回复,但是该ACK可能丢失。服务端如果没有收到ACK,将不断重复发送FIN片段。所以客户端不能立即关闭,它必须确认服务端接收到了该ACK,客户端会在发送出ACK之后进入到TIME_WAIT状态,客户端会设置一个计时器,等待2MSL的时间,如果在该时间内再次收到FIN,那么客户端会重发ACK并再次等待2MSL;所谓2MSL是两倍的MSL(Maximum Segment Lifetime)。MSL指一个片段在网络中最大的存活时间,2MSL就是一个发送和一个回复所需的最大时间。如果知道2MSL,客户端都没有再次收到FIN,那么客户端推断ACK已经成功接收,则结束TCP连接;

HTTP 和 HTTPS 的区别:

  • HTTPS 协议需要到 ca 申请证书(证书一般是收费的);
  • HTTPS 是具有安全性的 SSL 加密传输协议,而 HTTP 是超文本传输协议,信息是明文传输;
  • 两者是完全不同的连接方式,使用的端口号也不一样; HTTP:80 HTTPS:443;
  • HTTPS 协议是由 SSL+HTTP 协议构建的可进行加密传输,身份认证的网络协议; HTTP 是简单无状态的;

HTTPS的秘钥传输过程:

第一层是对称加密,但是对称加密需要一个秘钥,而以明文的方式传输加密秘钥的话非常不安全,那就在加一层非对称加密,而非对称加密就需要私钥(服务端保存)和公钥(客户端保存),客户端通过公钥去加密哪个对称秘钥,但是问题又来了就是客户端的公钥是从哪里来的呢?答案就是每个使用HTTPS的服务器都必须去专门的证书机构注册一个证书,证书中存储了使用权威机构私钥加密的公钥。这样客户端用权威机构的公钥去解密就可以了,但是问题又来就是权威机构的加密公钥又是怎么传输的呢?答案是这个公钥不用传输,而是会直接内置在各大操作系统(或者浏览器)的出厂设置里;之所以不把每个服务器的公钥都内置在电脑里,一方面是因为服务器太多存不过来;另一方面操作系统也不信任你,凭什么你说你这个是淘宝的正数呢?所以各个公司机构都必须先去权威机构认证,申请证书,然后操作系统只会存储权威机构的公钥;

Cookie和Session的区别:

HTTP是一种无状态的连接,客户端每次读取web网页时,服务器都会认为这是一次新的会话。但有时候我们需要持久保存一些用户信息,比如登录时的用户名和密码等;而这些信息都是需要Cookie和Session来保存; 这两个的本质区别就是Cookie是保存在客户端的,而Session是保存在服务器上的;

  • cookie 相对来说不安全,浏览器可以分析本地的 cookie 进行 cookie 欺骗。
  • session 可以设置超时时间,超过这个时间后就失效,以免长期占用服务端内存。
  • 单个 cookie 的大小有限制(4 Kb),每个站点的 cookie 数量一般也有限制(20个)。
  • 客户端每次都会把 cookie 发送到服务端,因此服务端可以知道 cookie,但是客户端不知道 session。

当服务器接收到 cookie 后,会根据 cookie 中的 SessionID 来找到这个客户的 session。如果没有,则会生成一个新的 SessionID 发送给客户端。

HTTP 和 socket 的区别:

HTTP 连接使用的是”请求–响应”的方式,不仅在请求时需要先建立连接,而且需要客户端向服务器发出请求后,服务器端才能回复数据;一次请求后立即断开;HTTP 使用的的面向连接的 TCP 作为传输层协议,保证了数据的可靠性;但是 HTTP属于无状态,无连接;虽然使用了 TCP 连接,但通信的双方不需要先建立连接;

socket 连接通常情况下就是 TCP 连接,因此 socket 连接一旦建立,通信双方即可开始互相发送数据内容,直到双方的连接断开;但在实际应用中,客户端和服务器之间的通行防火墙会关闭长时间处于非活跃状态的连接而导致 socket 连接中断,因此需要通过轮询告诉网络该连接处于活跃状态;

建立 socket 连接的过程:

连接过程分为三个步骤:服务器监听,客户端请求,连接确认; 服务器监听:服务器端套接字并不定位具体的客户端套接字,而是处于等待连接状态,实时监测网络状态,等待客户端的连接请求; 客户端的连接请求:指客户端的套接字提出连接请求,要连接的目标是服务器端的套接字,为此客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端的套接字的地址和端口号,然后就向服务器端套接字提出连接请求; 连接确认:当服务器端套接字监听到或者说收到客户端套接字的连接请求时,就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户端,一旦客户端确认了此描述,双方就正式建立连接,而服务器端的套接字继续处于监听状态,继续接受其它客户端套接字的连接请求;

HTTP

HTTP的 URL 的一般形式是: http://<主机>:<端口>/<路径> HTTP 的默认端口号是:80; HTTP 有两类报文: 1.请求报文---从客户端向服务器发送的请求报文 2.响应报文---从服务器到客户的回答

请求报文的组成:

  • 请求行:包含请求方法,请求资源路径,HTTP 协议的版本
  • 请求头:包含了对客户端的环境的描述,客户端请求的主机地址等信息; Host:192.168.12.105:8080 //客户端想访问的服务器的主机地址 User-Agent:Firefox/32.0 //客户端的类型,客户端的软件环境 Accept:text/html,/ //客户端所能接收的数据类型 Accept-Language: zh-cn //客户端的语言环境 Accept-Encoding:gzip //客户端支持的数据压缩格式

  • 请求体:客户端发给服务器的具体数据,比如文件数据;

响应报文的组成:

  • 状态行:包含了 HTTP协议版本,状态码,状态英文名称;
  • 响应头:包含了对服务器的描述,对返回数据的描述; Sever:Apache-Coyote/1.1 //服务器类型 Content_Type: image/jpeg //返回的数据类型 Content_Length:56811 //返回的数据长度 Date:Mon, 12 July 2016 12:54:39 GMT //响应时间
  • 实体内容:服务器返回给客户端的具体数据;

HTTP 的请求方法

GET

特点:所有的请求参数都拼接都 URL 的后面; 缺点:

  • 在 URL 中暴露所有的请求数据,不太安全;
  • URL 的的长度有限制不能发送太多的参数; 使用场合:如果仅仅是向服务器请求数据,一般使用 GET 请求;
POST

特点:

  • 所有的请求参数需要设置在请求体(HTTPBody)中;
  • 理论上讲发给服务器的数据大小是没有限制的;(主要看服务器的承载能力) 使用场合:
  • 除开向服务器请求数据以外的请求都可以使用POST 请求
  • 如果发给服务器的数据是一些隐私,敏感的数据,绝对要使用 POST 请求;

HTTP 状态码响应类型

1xx 保留.响应保留; 2xx 请求成功接收; 3xx 为完成请求客户端需要进一步细化请求; 4xx 客户端请求错误(参数,方式不正确); 5xx 服务器端有错误;

NSURLSession和NSURLConnection的区别

1.前者是在iOS97.0后推出的,用于代替后者的;后者是iOS2.0就推出的; 2.下载任务方式

  • 使用NSURLSession的时候,block和代理可以同时起作用,并且可以直接从文件系统上传、下载;不会出现内存暴涨的情况;下载文件的时候,默认会将文件下载到沙盒的tmp文件夹中,不会占多少内存,但是在下载完成后,会删除文件,所以要下载完成后需要添加相应的文件保存代码;
  • 使用NSURLConnection下载的时候,使用代理回调监听下载进度,并且下载过程中要手动管理内存,使用起来比较麻烦;NSURLConnection使用的是异步回调,先将数据下载到内存,等下载完毕后,在写入沙盒,如果文件很大,会导致内存暴增,并且使用异步回调无法监听下载进度; 3.请求方式的控制
  • NSURLSession有三个控制请求的方法,取消(cancel),暂停(suspend),继续(resume),暂停后可以通过继续恢复当前的请求任务;
  • NSURLConnection实例化对象,实例化开始,默认请求就发送(同步发送),不需要调用start方法;而cancel可以停止请求的发送,停止后不能继续访问,需要创建新的请求; 4.断点续传实现方式
  • NSURLSession进行断点下载,当暂停下载任务后,如果downloadTask(下载任务)为非空,调用 cancelByProducingResumeData:(void (^)(NSData *resumeData))completionHandler 这个方法,这个方法接收一个参数,完成处理代码块,这个代码块有一个NSData参数resumeData,如果resumeData非空,我们就保存这个对象到视图控制器的resumeData属性中;在点击再次下载时,通过调用[ [self.session downloadTaskWithResumeData: self.resumeData]resume]方法进行继续下载操作。
  • NSURLConnection进行断点下载,通过设置访问请求的HTTPHeaderField的Range属性,开启运行循环,NSURLConnection的代理方法作为运行循环的事件源,接收到下载数据时代理方法就会持续调用,并使用NSOutputStream(或者通过问卷指针)管道流进行数据保存; 5.NSURLSession 可以设置配置信息 NSURLSession的构造方法 (sessionWithConfiguration: delegate:delegateQueue)中有一个 NSURLSessionConfiguration类的参数可以设置配置信息,其决定了cookie,安全和高速缓存策略,最大主机连接数,资源管理,网络超时等配置。 NSURLConnection不能进行这个配置,相比于 NSURLConnection 依赖于一个全局的配置对象,缺乏灵活性而言,NSURLSession 有很大的改进了。 NSURLSession可以设置三种配置信息,分别通过调用三个类方法返回配置对象: +(NSURLSessionConfiguration *)defaultSessionConfiguration, 配置信息使用基于硬盘的持久化Cache,保存用户的证书到钥匙串,使用共享cookie存储; +(NSURLSessionConfiguration *)ephemeralSessionConfiguration 配置信息和default大致相同。除了,不会把cache,证书,或者任何和Session相关的数据存储到硬盘,而是存储在内存中,生命周期和Session一致。比如浏览器无痕浏览等功能就可以基于这个来做; +(NSURLSessionConfiguration *) backgroundSessionConfigurationWithIdentifier:(NSString *)identifier 配置信息可以创建一个可以在后台甚至APP已经关闭的时候仍然在传输数据的session。注意,后台Session一定要在创建的时候赋予一个唯一的identifier,这样在APP下次运行的时候,能够根据identifier来进行相关的区分。如果用户关闭了APP,IOS 系统会关闭所有的background Session。而且,被用户强制关闭了以后,IOS系统不会主动唤醒APP,只有用户下次启动了APP,数据传输才会继续。 6.NSURLSession 支持HTTP 2.0
最近的文章

多线程

多线程什么是多线程?多线程就是一个进程中可以开启多条线程,每条线程可以并行执行不同的任务,提高执行效率;一个基本概念就是同时对多个任务加以控制;多线程分为主线程和子线程;一个iOS程序运行后,默认会开启1条线程,称为“主线程”或“UI线程”;主线程的主要作用显示\刷新UI界面\处理UI事件(比如点击事件、滚动事件、拖拽事件等);子线程主要用来做一些耗时操作;每一个iOS应用程序中都有一个主线程用来更新UI界面、处理用户的触摸事件、解析网络下载的数据,因此不能把一些太耗时的操作(比如网络下载...…

继续阅读
更早的文章

设计模式

MVC:Model: 负责存储,定义,操作数据;View: 用来展示给用户数据,和用户进行交互操作的;Controller:是 View 和 Model 的协调者,其可以直接与 Model 和 View 通信;而 View 不能和 Controller直接通信,需要利用代理协议的方式才能间接进行通信;或者通过 target-action 的方式进行通信, target 会留出 outlet 接口供 Controller 调用;同样 Model 和 Controller 也不能进行直接的通信...…

继续阅读