Network Summary

Posted by syea on July 23, 2018

Network Summary

目录:

  • 常见的客户端请求流程
  • 如何优化网络请求
  • 扩展一:Https
  • 扩展二:AFNetworking

常见的客户端请求流程

自己整理了一下,画了一张流程图,常规的基于 TCP/IP 的请求流程。

如何优化网络请求

1. 客户端发起请求

这个在 iOS 端一般都是借助第三方网络库,创建好参数然后发起请求。当然用系统原生的也完全 ok,毕竟第三方库也只是对系统网络请求的一个比较好(非常好)的封装。这里是客户端可控区域,再往下就很难控制了。优化的点有

  1. 参数配置
    比如NSURLSession里有一个属性
    /* Allow the use of HTTP pipelining */
    @property BOOL HTTPShouldUsePipelining;
    

    设置这个属性可以开启请求管道,原理和优缺点会在下文叙述。

  2. 压缩报文
    加快请求报文的传输。
2. DNS 查询

一般请求会向域名发起而不会直接通往目标 ip 地址,这个时候就需要做 DNS 查询,简单的说就是通过域名查询到目标服务器的 ip 地址。这个点至少有两个地方可以优化。

  1. 查询速度。一般 DNS 都有缓存,也会设一个缓存过期时间,这就导致了查询时间的不稳定。
  2. DNS 劫持。经常有运营商劫持 DNS,强行扔几个广告给你看。

这里业界一般采用HTTPDNS来优化上述两个方面。查询了一下似乎是要收费的,目前项目中也没有尝试..

3. 3次握手建立连接

第一次建立连接,3次握手必不可少。这里可以优化的点在于,在很多个请求的情况下,如何减少建立连接的时耗. 这里引用一张《HTTP权威指南》中的原图,比较直观。

一般情况下,HTTP/1.1 的持久连接在默认情况下是激活的,除非特别指明,否则 HTTP/1.1假定所有连接都是持久的。

这也就意味着我们一般在客户端发多个请求可以采用第二种方式,不用每次发请求都要进行3次握手了。那么这里还能优化吗? 可以看到,第三种管道化持久连接的方式好像更酷,耗时也比第二种更少。但是这中管道化连接有比较大的限制。

  1. 需要服务器支持
  2. 不能(不应该)以管道化方式传送非幂等请求(Post)
  3. 客户端应该要能确认连接是持久的
  4. 响应返回的顺序应该跟请求对应起来
  5. 客户端必须做好连接会随时断开的准备

emmmm… 那么我们还是采用第二种吧。(那特么不是根本没优化吗,我们好像什么都没做啊)
顺带一提,HTTP2.0 有个比较好的机制:多路复用,极大地提高了请求速度。

关于客户端与服务器的长连接,我有一些疑问

  1. 我们平常写请求代码的时候,是每次都重新建立连接还是只有第一次建立连接,之后都是在这条持久连接里面
  2. 客户端与服务器的 TCP 长连接是与 NSURLSession 对应还是 NSURLSessionTask 还是 NSURLRequest?
  3. 如何验证客户端的一个请求是否与服务器进行了三次握手?
4. 传送请求报文

这个不太好做优化,毕竟已经是数据链路层和物理层的事情了。这里可以考虑在第二个阶段,返回服务器 ip 地址的时候,返回一个离用户比较近的 ip(大厂专用优化)。

5. 服务器处理

这里就是写后台朋友的优化了。

  1. 数据查询方向(sql 优化、redis…)
  2. 数据处理方向(算法优化…) …
6. 返回响应报文

这个同第4点

7. 4次挥手断开连接

这个好像真没法优化

8. 客户端处理数据

这里跟程序员的数据结构、算法水平相关。比如后台返回了一棵比较复杂的树,怎么处理更好?一般情况下只是简单的 Array、Map 应该处理起来问题不大。

9. 刷新 UI

这一点其实跟网络已经没什么关系了,主要是一些空间跟时间的取舍。比如要展示一个新闻列表

  1. 先不画 UITableView ,获取到数据了再实例化 UITableView 并展示。
  2. 直接实例化空的 UITableView, 获取到数据后再 reloadData
10. 缓存策略

以上的优化都是基于与服务器交互的前提下,当我们已经请求过某个接口后,再次需要数据的时候,其实可以完全避免上述操作。
那么如何来缓存请求数据呢?我个人是采用了 YYCache 第三方库来实现的。

扩展一:Https

如果简单地理解 Https 的话,就是采用了对称加密和非对称加密的 Http,它比起 Http 多了一层 SSL 安全层。 比起简单的 Http,Https 建立连接时多了 SSL 握手。 SSL 握手后就跟普通的 TCP 连接一样啦,不过每次这样也挺耗时的,Https 也进行了很多优化,比如 session 复用。

btw,以前也写过一篇关于 Https 的博客,那时了解了一下对称加密跟非对称加密,然后记录了下来。觉得了解的应该差不多了,然后有次被别人问起 Https,讲了之后对方还是不停地深入发问,然后就蒙蔽了,所以这次总结网络的时候顺便又去学了一下。

扩展二:AFNetworking

这里提一下 AFNetworking,因为这是iOS最常用的网络库。
核心类:AFURLSessionManager,负责请求的发起、调度、回调。 安全类:AFSecurityPolicy, 负责 HTTPS 验证。 检测类:AFNetworkReachabilityManager, 负责检测客户端网络连接情况。 解析类:AFHTTPRequestSerializer,AFURLResponseSerialization,负责设置请求报文和响应报文。

简单画一下流程图,如有错误请联系我指出,万分感谢。