iOS 的 Reachability 你使用的对吗?

iOS 的 Reachability 你使用的对吗?

问题背景: 在使用Reachability监听网络时, 在初次启动以后多次回调!

最近在开发一个项目时, 使用iOS的官方DemoReachability, 几乎没有思考就直接使用原来项目中的代码:

  // 监听 remote host name
  // Change the host name here to change the server you want to monitor.
  NSString *remoteHostName = @"www.baidu.com";
    // 创建一个 host 链接检测器 -> 首先进行DNS解析!!!
    self.hostReachability = [Reachability reachabilityWithHostName:remoteHostName];
    [self.hostReachability startNotifier]; // 启动监听

但是最近在ceshi-wifi(only-v6)情况下, 网络状态的callback回调总是展示NotReachable !!!

在仔细研究了Apple的Demo Reachability 以后, 有了答案, 具体关键信息如下:

Note: Reachability cannot tell your application if you can connect to a particular host, only that an interface is available that might allow a connection, and whether that interface is the WWAN. To understand when and how to use Reachability

简单点说, Reachability能做的就是:

  1. 可以告诉你哪个网口可以与给定的Host建立连接.
  2. 可以建立的网口究竟是WIFI还是WWAN, 如果是WWAN, 那么具体是3g, 4g or 5g!

然后针对Demo中的两个核心API, Demo也拥有如下解释:

- reachabilityWithHostName and SCNetworkReachabilityCreateWithName:  Internally, this API works be resolving the host name to a set of IP addresses (this can be any combination of IPv4 and IPv6 addresses) and establishing separate monitors on all available addresses.

- reachabilityWithAddress and SCNetworkReachabilityCreateWithAddress:  To monitor an IPv6 address, simply pass in an IPv6 `sockaddr_in6 struct` instead of the IPv4 `sockaddr_in struct`.

- reachabilityForInternetConnection:  This monitors the address 0.0.0.0, which reachability treats as a special token that causes it to actually monitor the general routing status of the device, both IPv4 and IPv6.

简单解释:

  1. reachabilityWithHostName, 调用这个API以后, 操作系统首先会使用LocalDNS解析Host对应的IP List(可能有多个IP, 并且可能IPv4&IPv6都有), 然后底层会针对各个IP, 去建立多个监听器去针对all available addresses!!!

    1. 这里availabel addresses 值得研究! 举个例子, 我们在上面在ipv6-only的wifi中, 监听www.baidu.com , baidu的只有ipv4-only的ip, 因此是not available 的!!!
    2. 方案会使用LocalDNS服务去解析Host! 这里很有可能因为DNS解析缓慢, 从而导致我们在callback回调中收到多次信息, 在DNS解析还没有成功时, 收到Not Reachable, 在DNS解析成功, 获取IP并建立监听以后, 监听到Reachable!!!
  2. reachabilityForInternetConnection 方案使用0.0.0.0这个特殊的IP, 是让操作系统帮我们监听是否在本地网络连接中有出口路由, 或者说是否有本地网关gateway, 并且会同时监听Ipv4Ipv6的出口gateway

另外Apple 在Demo中提示:


By default, the application uses www.apple.com for its remote host. You can change the host it uses in APLViewController.m by modifying the value of the remoteHostName variable in -viewDidLoad.
 
IMPORTANT: Reachability must use DNS to resolve the host name before it can determine the Reachability of that host, and this may take time on certain network connections.  Because of this, the API will return NotReachable until name resolution has completed.  This delay may be visible in the interface on some networks.
 
The Reachability sample demonstrates the asynchronous use of the SCNetworkReachability API. You can use the API synchronously, but do not issue a synchronous check by hostName on the main thread. If the device cannot reach a DNS server or is on a slow network, a synchronous call to the SCNetworkReachabilityGetFlags function can block for up to 30 seconds trying to resolve the hostName. If this happens on the main thread, the application watchdog will kill the application after 20 seconds of inactivity.
 
SCNetworkReachability API's do not currently provide a means to detect support for device level peer-to-peer networking, including Multipeer Connectivity, GameKit, Game Center, or peer-to-peer NSNetService.

关键信息如下:

  1. 由于reachabilityWithHostName会使用DNS, 而DNS耗时不定, the API will return NotReachable until name resolution has completed!
  2. 注意使用reachabilityWithHostName时, 由于DNS解析时间不定, 也有可能会解析失败从而导致超时, 超时时间长达20+s. 因此Apple 建议我们不要使用同步API, 而是添加到Runloop中, 使用异步方式调用API. 具体异步的方式参考demo.

另外Apple也告知了, 我们针对Reachability的最佳实践Reachability最佳实践, 简单总结一下:

如果是用户操作触发的网络请求:

  1. 如果网络连接失败了, 可以创建SCNetworkReachability 去检测具体失败的原因

    1. 如果是因为传输过程失败, 那么重新连接
    2. 如果是因为host unreachable!!! 最好等待我们注册的Reachability callback 回调, 等待 Host Reachable 以后, 重新连接!
  2. 不要在每个网络请求之前调用SCNetworkReachability 去检测Host的reachable!!!!

  3. 并且即使我们通过SCNetworkReachability 检测到指定的 Host 是使用WWAN也并不表名, 请求并不一定会从WWAN发出!!

最终我们的总结如下:

  1. 如果我们需要监听本地的网络连接状态!!! 使用reachabilityForInternetConnection ,一般而言我们对APP进行全局监听的时, 基本用这个就行!!!
  2. 如果我们需要针对某一个Host监听它的状态(监听的是DNS解析后的Ipv4/Ipv6), 使用reachabilityWithHostName
  3. 注意SCNetworkReachability返回Reachable并不保证指定的Host可以访问到!!! 只是数据会从设备终端发出!!! 能不能被对端的Host接受是另外一码事, 如果需要知道是能否对对端Host接受到, 请使用PING/PING6, 或者第三方的 RealReachability

reachabilityWithHostName 监听的Host一定是在项目中关注的某个接口的Host, 而不是我们随便设置的一个Host

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 151,511评论 1 330
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 64,495评论 1 273
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 101,595评论 0 225
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 42,558评论 0 190
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 50,715评论 3 270
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 39,672评论 1 192
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,112评论 2 291
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 29,837评论 0 181
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,417评论 0 228
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 29,928评论 2 232
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,316评论 1 242
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 27,773评论 2 234
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,253评论 3 220
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,827评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,440评论 0 180
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 34,523评论 2 249
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 34,583评论 2 249

推荐阅读更多精彩内容

  • Reachability类的学习 简介 Reachability类是Apple官方出的判断当前网络状况的工具类,这...
    ashura_阅读 2,249评论 3 1
  • This API is part of Core Foundation, so it written in C. ...
    Code匠阅读 668评论 1 1
  • 第一章 运行循环 运行循环是由类 NSRunLoop 表示的,有些线程可以让操作系统唤醒睡眠的线程以管理到来的事件...
    bearIT阅读 284评论 0 0
  • 碰到的问题: 如果传入的 hostname 带有 http prefix,则有网络也会返回 not reach。如...
    Yang152412阅读 1,053评论 0 51
  • 在iOS开发中不可避免的会用到一些第三方类库,它们提供了很多实用的功能,使我们的开发变得更有效率;同时,也可以从它...
    蘇哲炫爺阅读 859评论 0 0