Skip to content

Latest commit

 

History

History
141 lines (96 loc) · 13.8 KB

网络.md

File metadata and controls

141 lines (96 loc) · 13.8 KB

网络专场

网络优化方案都有哪些?

TCP的三次握手是什么?

这张图描述了三次握手的过程:
三次握手

第一次握手:建立连接。客户端发送连接请求报文段,将SYN位置为1,Sequence Number为x;然后,客户端进入SYN_SEND状态,等待服务器的确认;
第二次握手:服务器收到SYN报文段。服务器收到客户端的SYN报文段,需要对这个SYN报文段进行确认,设置Acknowledgment Number为x+1(Sequence Number+1);同时,自己自己还要发送SYN请求信息,将SYN位置为1,Sequence Number为y;服务器端将上述所有信息放到一个报文段(即SYN+ACK报文段)中,一并发送给客户端,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK报文段。然后将Acknowledgment Number设置为y+1,向服务器发送ACK报文段,这个报文段发送完毕以后,客户端和服务器端都进入ESTABLISHED状态,完成TCP三次握手。

SYN, ACK都是TCP报文头部中的标志位,为1表示被置。
三次握手的本质:
这个问题的本质是, 信道不可靠, 但是通信双发需要就某个问题达成一致. 而要解决这个问题, 无论你在消息中包含什么信息, 三次通信是理论上的最小值. 所以三次握手不是TCP本身的要求, 而是为了满足"在不可靠信道上可靠地传输信息"这一需求所导致的. 请注意这里的本质需求,信道不可靠, 数据传输要可靠. 三次达到了, 那后面你想接着握手也好, 发数据也好, 跟进行可靠信息传输的需求就没关系了. 因此,如果信道是可靠的, 即无论什么时候发出消息, 对方一定能收到, 或者你不关心是否要保证对方收到你的消息, 那就能像UDP那样直接发送消息就可以了.

“三次握手”的目的是“为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误”。“已失效的连接请求报文段”的产生在这样一种情况下:client发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达server。本来这是一个早已失效的报文段。但server收到此失效的连接请求报文段后,就误认为是client再次发出的一个新的连接请求。于是就向client发出确认报文段,同意建立连接。假设不采用“三次握手”,那么只要server发出确认,新的连接就建立了。由于现在client并没有发出建立连接的请求,因此不会理睬server的确认,也不会向server发送数据。但server却以为新的运输连接已经建立,并一直等待client发来数据。这样,server的很多资源就白白浪费掉了。采用“三次握手”的办法可以防止上述现象发生。例如刚才那种情况,client不会向server的确认发出确认。server由于收不到确认,就知道client并没有要求建立连接。”

如何防止网络劫持的发生?

iOS 客户端对于运营商劫持的一点点对抗方式
NSURLProtocol:DNS劫持和Web资源本地化
可能是最全的iOS端HttpDns集成方案
移动开发构架漫谈——反劫持实战篇
iOS强制ATS后,DNS劫持问题如何解决?

网络劫持一般有两种情况,一种是DNS劫持,另一种是HTTP劫持。

从表现上区分这两种劫持非常简单。

如果是DNS劫持,你输入的网址是google.com,然后出来的页面是百度。

如果是HTTP劫持,你打开了google.com,可是右下角弹出了百度推广的不孕不育广告。

URL域名解析成ip地址的过程被称作 DNS 解析。在这个过程中,由于 DNS 请求报文是明文状态,可能会在请求过程中被监测,然后攻击者伪装DNS服务器向主机发送带有假ip地址的响应报文,从而使得主机访问到假的服务器。这个就是DNS劫持的根本原理。

而另一种就是HTTP劫持。在运营商的路由器节点上,设置协议检测,一旦发现是HTTP请求,而且是html类型请求,则拦截处理。后续做法往往分为2种,1种是类似DNS劫持返回302让用户浏览器跳转到另外的地址,还有1种是在服务器返回的 HTML 数据中插入 js 或 dom 节点,从而使网页中出现自己的广告等等垃圾信息。

一般来说,针对各种网络劫持,大部分工作都是由前端来完成,针对这一方面的研究,也大多都是前端开发方向。但是其实客户端也可以通过一些方法来防劫持。

  • DNS劫持
    一般情况下,考虑DNS劫持大多发生在使用webview的时候。相较于使用网页,正常的网络请求,即便被劫持了无非是返回错误的数据,或者干脆404。
    可以基于NSURLProtocol实现LocalDNS防劫持方案。 简单来说,在网页发起请求的时候获取请求域名,然后在本地进行解析得到ip,返回一个直接访问网页ip地址的请求。DNS防劫持这篇文章里有示例代码。

什么是长连接?有没有优化方案?

TCP连接在长时间没有数据传输的时候,会断开连接。为了实现长连接,就要定期的发送心跳数据。所谓的长连接并没有什么高深的地方,就是想办法让一个TCP连接长时间的保持。

心跳包,通常是客户端每隔一小段时间向服务器发送的一个数据包,通知服务器自己仍然在线,并传输一些可能有必要的数据。因按照一定的时间间隔发送,类似于心跳,所以叫做心跳包。事实上为了保持长连接,至于包的内容,是没有特别规定的,不过一般都是很小的包,或者只是包含包头的一个空包。

在TCP协议的机制里面,本身是存在有心跳包机制的,也就是TCP协议中的SO_KEEPALIVE,系统默认是设置2小时的心跳频率。要用setsockopt将SOL_SOCKET.SO_KEEPALIVE设置为1才是打开,并且可以设置三个参数tcp_keepalive_time/tcp_keepalive_probes/tcp_keepalive_intvl,分别表示连接闲置多久开始发keepalive的ACK包、发几个ACK包不回复才当对方死了、两个ACK包之间间隔多长。

至于优化方案,这个通过Google搜索不到。

什么是TCP通讯过程中出现的粘包现象?如何封包和拆包?

首先明确2点:

  1. 这里的包是指应用层面的消息包
  2. 使用UDP协议进行通信时不会有此问题,因为存在保护消息边界,就是指传输协议把数据当作一条独立的消息在网上传输,接收端只能接收独立的消息。

TCP协议发送的数据,是流式的,没有保护消息边界。所谓的粘包现象,是指消息包在客户端粘在一起了,需要拆包。
粘包产生的原因:

  1. 发送方引起。这个是由TCP协议本身造成的,TCP为提高传输效率,发送方往往要收集到足够多的数据后才发送一包数据。若连续几次发送的数据都很少,通常TCP会根据优化算法把这些数据合成一包后一次发送出去,这样接收方就收到了粘包数据。
  2. 接收方引起的粘包是由于接收方用户进程不及时接收数据,从而导致粘包现象。

其实这个问题也没有啥含量,封包的时候肯定得有定长的头部字段,里面可以读出来消息体的长度。而在客户端,读socket的时候可以指定读取多少字节。那么客户端可以一直重复一个循环:读头部,解析出消息体的长度,然后再读相应长度的字节。

JSON协议支持的数据类型都有哪些?

支持的:
a string
a number
an object(JSON object)
an array
a boolean
null

不支持的:
a function
a date
undefined

HTTP/2.0

1. HTTP2.0的前世

http2.0的前世是http1.0和http1.1这两兄弟。http1.0诞生于1996年,协议文档足有60页。之后第三年,http1.1也随之出生,协议文档膨胀到了176页。

1.1 HTTP站在TCP之上

HTTP协议的瓶颈及其优化技巧都是基于TCP协议本身的特性。比如TCP建立连接时三次握手有1.5个RTT(round-trip time)的延迟,为了避免每次请求都经历握手带来的延迟,应用层会选择不同策略的http长链接方案。又比如TCP在建立连接的初期有慢启动的特性,所以连接的重用总是比新建连接性能要好。

1.2 因为延迟,所以慢

影响一个网络请求的因素主要有两个,带宽和延迟。当前带宽已经不是问题,所以大部分时候都是延迟在影响响应速度。http1.0被抱怨最多的就是连接无法复用,和head of line blocking这两个问题。

连接无法复用会导致每次请求都经历三次握手和慢启动。三次握手在高延迟的场景下影响较明显,慢启动则对文件类大请求影响较大。

head of line blocking会导致带宽无法被充分利用,以及后续健康请求被阻塞。对于http1.0的实现,在第一个请求没有收到回复之前,后续从应用层发出的请求只能排队。

1.3 解决连接无法复用

http1.0协议头里可以设置Connection:Keep-Alive。在header里设置Keep-Alive可以在一定时间内复用连接,具体复用时间的长短可以由服务器控制,一般在15s左右。到http1.1之后Connection的默认值就是Keep-Alive,如果要关闭连接复用需要显式的设置Connection:Close。一段时间内的连接复用对PC端浏览器的体验帮助很大,因为大部分的请求在集中在一小段时间以内。但对移动app来说,成效不大,app端的请求比较分散且时间跨度相对较大。所以移动端app一般会从应用层寻求其它解决方案,长连接方案或者伪长连接方案:

方案一:基于TCP的长链接
方案二:Web Socket
WebSocket和传统的tcp socket连接相似,也是基于tcp协议,提供双向的数据通道。WebSocket优势在于提供了message的概念,比基于字节流的tcp socket使用更简单,同时又提供了传统的http所缺少的长连接功能。

1.4 解决head of line blocking

该问题是http2.0之前网络体验的最大祸源。为了解决holb带来的延迟,协议设计者设计了一种新的pipelining机制。这该机制并未彻底解决问题,响应还是要求依次返回。因此各大浏览器厂商要么是根本就不支持pipelining,要么就是默认关掉了pipelining机制,而且启用的条件十分苛刻。

2.开拓者SPDY

http1.0和1.1虽然存在这么多问题,业界也想出了各种优化的手段,但这些方法手段都是在尝试绕开协议本身的缺陷,都有种隔靴搔痒,治标不治本的感觉。直到2012年google如一声惊雷提出了SPDY的方案,大家才开始从正面看待和解决老版本http协议本身的问题,这也直接加速了http2.0的诞生。实际上,http2.0是以SPDY为原型进行讨论和标准化的。为了给http2.0让路,google已决定在2016年不再继续支持SPDY开发,但在http2.0出生之前,SPDY已经有了相当规模的应用,作为一个过渡方案恐怕在还将一段时间内继续存在。现在不少app客户端和server都已经使用了SPDY来提升体验,http2.0在老的设备和系统上还无法使用(iOS系统只有在iOS9+上才支持),所以可以预见未来几年spdy将和http2.0共同服务的情况。

2.1 SPDY的目标

SPDY的目标在一开始就是瞄准http1.x的痛点,即延迟和安全性。我们上面通篇都在讨论延迟,至于安全性,由于http是明文协议,其安全性也一直被业界诟病,不过这是另一个大的话题。如果以降低延迟为目标,应用层的http和传输层的tcp都是都有调整的空间,不过tcp作为更底层协议存在已达数十年之久,其实现已深植全球的网络基础设施当中,如果要动必然伤经动骨,业界响应度必然不高,所以SPDY的手术刀对准的是http。

  • 降低延迟,客户端的单连接单请求,server的FIFO响应队列都是延迟的大头。
  • http最初设计都是客户端发起请求,然后server响应,server无法主动push内容到客户端。
  • 压缩http header,http1.x的header越来越膨胀,cookie和user agent很容易让header的size增至1kb大小,甚至更多。而且由于http的无状态特性,header必须每次request都重复携带,很浪费流量。

SPDY的设计如下:

其位于HTTP之下,TCP和SSL之上,这样可以轻松兼容老版本的HTTP协议,同时可以使用已有的SSL功能。

SPDY的基础功能有:

  • 多路复用
  • 请求优先级
  • 头部压缩

SPDY的高级功能有:

  • server push 开启server push之后,server通过X-Associated-Content header告知客户端会有新的内容推送过来。在用户第一次打开网站首页的时候,server将资源主动推送过来可以极大的提升用户体验。
  • server hint 和server push不同的是,server hint并不会主动推送内容,只是告诉有新的内容产生,内容的下载还是需要客户端主动发起请求。
2.2 SPDY的成绩

页面加载时间相比于http1.x减少了64%。而且各大浏览器厂商在SPDY诞生之后的1年多里都陆续支持了SPDY,不少大厂app和server端框架也都将SPDY应用到了线上的产品当中。

https://www.zhihu.com/question/34074946

http常见头部和状态码

http缓存

什么叫大前端?为什么叫大前端?有哪些技术?

IM