谈谈iOS中的网络

最近工作比较轻松,所以有时间来好好思考一下自己代码里面的一些架构的问题,当然了,因为自己本身其实能力还不足以当一个架构师,所以才会有那么多的架构问题,那么在这里就聊聊网络那点事。

  • 网络是怎样连接的
  • iOS中的网络模块构建

网络是怎样连接的

最开始的起因是在一次面试中,发现自己其实只懂得在iOS中怎么去进行网络请求、返回的json数据怎么解析等等一些业务层上的操作,而对网络底层应该去做的一些连接步骤,三次握手的必要性等等都很是模糊不清的,所以就买了一些书好好去看了看,好歹是能说清楚网络是怎么去连接的了,话说。。。上学时没有好好学通讯基础、计算机组成原理啥的,现在很是有点伤啊(′⌒`)

那么接下来说说网络连接的具体过程:

生成请求 -> 访问DNS服务器获取具体IP地址 -> 连接接收端(传说中的三次握手就在这),Https也是在这里会进行证书下载,以便进行以后的数据加密,这块先不讲 -> 根据TCP协议进行数据分割(分成包) -> IP协议计算路由(也可以说是传输路径) -> 通知网卡驱动准备发送 -> 网卡发送数据包 -> 接收端根据TCP协议,返回收到的包结果,确定需不需要重发丢失的数据包并进行数据拼接 -> 接收端获取到拼接好的数据

以上就是一次网络请求的具体操作步骤,下面会好好聊聊里面的一些东西。

1.TCP/IP协议

TCP协议和IP协议其实是两个不同的协议,负责的内容也完全不同,通常是由TCP协议去调起IP协议,具体得关系应该如下图,但是这个真的是很大的内容,反正我是不敢说自己已经完全懂这块的内容了,就先说说我知道的一些内容吧。

TCP/IP协议

在上面其实有提到过,TCP协议其实是负责请求数据的分割,因为请求数据太大了,不能在一次传输就把所有内容全部传输过去,所以诞生了TCP协议,用以做内容分割,而对应的,接受端也要遵循TCP协议,在接受到数据包就得返回给请求端接受结果,以便确定数据包有没有丢失,是不是需要重发,而接收端在接受完了全部的内容之后(如何确定是否接受到全部的数据包当然也是TCP协议的内容),进行数据拼接。

但是因为TCP协议需要保证请求数据能完整传输到接受端,需要去做大量的工作,那么对应的,就有UDP协议,把所有的内容一次性地去发送给接收端,接收端接受之后返回结果,丢失就全部重发,这样是不能做到一些日常的网络请求的,因为容量太小了,但是在某些场景会使用到。PS:应用场景我还没有想到(⊙﹏⊙)

IP协议负责的是把数据包从请求端发送到接收端,包括寻址分段这两个内容,而确定数据传输路径的是路由算法(优秀的路由算法可以大幅度提高数据传输效率,尽管分配的带宽并没有改变,所以好的路由器是很重要的 o( ̄ヘ ̄o#) )

2.DNS服务器

DNS服务器,就是把英文的域名解析成对应的主机IP地址的服务器,跟所有的服务器一样,DNS服务器上面并不仅仅是保存域名-IP地址而已,因为网络访问太过频繁的关系,基本上大型的服务器系统都会做 负载均衡 而负载均衡中很重要的一点就是在DNS服务器返回的时候需要其返回正确的、压力比较小的主机IP地址。但这块我并不是很熟悉,只是知道负载均衡需要从这块入手。。。。。。


iOS中的网络模块构建

跟其他的功能模块一样,把网络功能单独做成功能模块主要是为了减少重复代码和复用,而且在iOS中,目前比较火的网络请求框架是AFNetWorking,但是风水轮流转,起码得保证到时候需要去更换成其他的第三方框架或者直接上NSURLSession也好,工作量不会那么得大,维护起来会比较省心。

所以我封装网络模块基本思路如下图:

模块封装

1.业务层 (Manager)

这一层的网络模块主要是做跟API接口的对接,通过大量的注释来作为API接口的说明和目录,而通常情况下,新增API接口或者API接口出现改动,都只需要修改这一层的东西。

简单点说,这个模块是一个类(下面统称 NetworkManager),这个NetworkManager是单例的(方便进行逻辑层的连接,然后会带有几个简单的属性)

#import <Foundation/Foundation.h>
#import "NetworkTool.h"
#import "NetworkHandler.h"

@interface NetworkManger : NSObject

@property (strong, nonatomic) NetworkHandler *handler;

+ (instancetype)shareManger;

//根据API制定网络访问方法.....这里举个栗子
#pragma mark - 获取用户信息
/**
 *  获取用户信息
 *  
 *  @param userId 用户的id
 *  @param result 回调
 */
- (void)getUserInfo:(NSInteger)userId callBack:(void (^)(id))result;

@end

在网络访问方法中,会使用核心层进行网络请求,然后返回的结果需要先通过逻辑层(如果API接口有要求的话,在调用核心层Tool进行请求之前,先用逻辑层handler进行数据的加密等操作),判断请求结果是否有正确,同时如果返回结果是正常的时候调用传入的block来进行数据的填充或者保存。

实现的例子就不给出了,主要是要做下面几个步骤:

Handler处理传入参数(例子里面就是userId) -> 处理好的参数作为参数,调用Tool的GET或者POST方法(这个一般是封装的第三方请求框架) -> Handler处理返回结果(response) -> Handler处理后返回数据作为参数,执行回调block;

2.逻辑层 (Handler)

说白了,这个层其实是为了把每个API接口大同小异的错误返回进行过滤,如果是返回错误的结果,就直接使用Handler来进行处理和提示,这样就不用在功能模块外部再次判断返回的数据是否出错等问题,修改起来会比较方便。

#import <Foundation/Foundation.h>

@interface NetworkHandler : NSObject

/**
 *  处理传给API的参数
 */
+ (NSDictionary *)handleParams;

/**
 *  对API返回的数据进行处理;
 *  
 *  @param networkData API返回数据
 *  @param result      返回结果正确时候的回调
 */
+ (void)handleNetworkResult:(id)networkData callback:(void (^)(id))result;

@end

3.核心层

核心层只需要负责根据参数和URL进行对应的GET和POST操作就结束了,它的存在意义是在需要进行网络方法更换的时候不需要去修改太多的东西。

@interface NetWorkTool : NSObject

/**
 *  POST的访问
 *
 *  @param URLString  URL地址
 *  @param parameters Dicionary(nil),参数
 *  @param sucess     成功回调
 *  @param failure    失败回调
 */
+ (void)POST:(NSString *)URLString parameters:(id)parameters success:(void (^)(id))sucess failure:(void (^)(NSError *))failure;

/**
 *  POST的访问
 *
 *  @param URLString  URL地址
 *  @param parameters Dicionary(nil),参数
 *  @param sucess     成功回调
 *  @param failure    失败回调
 */
+ (void)GET:(NSString *)URLString parameters:(id)parameters success:(void (^)(id))sucess failure:(void (^)(NSError *))failure;

@end

猜你喜欢

转载自blog.csdn.net/u1031/article/details/73547834