【问题标题】:How to write a simple Ping method in Cocoa/Objective-C如何在 Cocoa/Objective-C 中编写一个简单的 Ping 方法
【发布时间】:2025-12-10 17:15:02
【问题描述】:

我需要在 Cocoa/Objective-C 中编写一个简单的ping 方法。它还需要在 iPhone 上运行。

我找到了一个使用 icmp 的示例,这可以在 iPhone 上使用吗?

我倾向于使用NSNetServices 的解决方案,这是个好主意吗?

该方法只需ping 几次,如果主机宕机或无法访问,则返回平均值和-1。

【问题讨论】:

    标签: iphone objective-c cocoa cocoa-touch networking


    【解决方案1】:

    注意-我会推荐 Chris 在下面的解决方案,它实际上直接回答了所提出的问题。这篇 12 年前的帖子是为了回应原作者赞成的答案,对此我有更好的解决方案。由于作者赞成上面使用可达性的答案,我认为他实际上对可达性比实际上对发送 ping 更感兴趣,因此我的回答。请在否决此答案之前考虑这一点。

    StreamSCNetworkCheckReachabilityByName 已弃用,不适用于 iPhone。 注意:SystemConfiguration.framework 是必需的

    bool success = false;
    const char *host_name = [@"*.com" 
                             cStringUsingEncoding:NSASCIIStringEncoding];
    
    SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL,
                                                                            host_name);
    SCNetworkReachabilityFlags flags;
    success = SCNetworkReachabilityGetFlags(reachability, &flags);
    
    //prevents memory leak per Carlos Guzman's comment
    CFRelease(reachability);
    
    bool isAvailable = success && (flags & kSCNetworkFlagsReachable) && 
                                 !(flags & kSCNetworkFlagsConnectionRequired);
    if (isAvailable) {
        NSLog(@"Host is reachable: %d", flags);
    }else{
        NSLog(@"Host is unreachable");
    }
    

    【讨论】:

    • 嗨。优秀的代码和有用的,但只有一件事。您需要在调用SCNetworkReachabilityGetFlags 之后添加代码CFRelease(reachability) 以释放可达性变量(以防止内存泄漏),如documentation 中所述
    • SCNetworkReachabilityGetFlags 是 ping 的不良替代品——如果设备连接到网络,即使目标主机离线,kSCNetworkFlagsReachable 将被设置,kSCNetworkFlagsConnectionRequired 将被取消设置。跨度>
    • 我正在改进接受的答案。我不争论 SCNetworkReachabilityGetFlags 是 'ping' 的糟糕替代品,但如果你只是想确定可达性,就像 rjstelling 目标一样,那么这是一个很好的解决方案。如果您需要监控延迟或提供心跳,那么“ping”解决方案可能会更好。
    【解决方案2】:

    我遇到了同样的问题,最后围绕 SimplePing 编写了一个简单的包装器来实现这一点,写了一篇关于它的博客,并且在 github 上有一些代码,希望对这里的人有所帮助:

    http://splinter.com.au/how-to-ping-a-server-in-objective-c-iphone

    【讨论】:

    • 支持一个真正回答问题的解决方案(与人们似乎喜欢但完全没有解决问题的所有这些无用的可达性问题相比!)。谢谢!
    • 是的,这是真正的答案。
    【解决方案3】:

    您没有遗漏任何东西——“可达性”实际上并没有测试目标域实际上是否可访问,它仅评估是否存在从机器出来的路径,通过该路径可以访问目标域。只要您有一些出站连接(例如,活动的无线或有线连接)和通向目标的路由配置,那么就 SCNetworkReachability 而言,该站点是“可访问的”。

    【讨论】:

      【解决方案4】:

      由于您没有 root 访问权限,因此在 iPhone 上 Ping 的工作方式与在其他平台上略有不同。请参阅来自 Apple 的 sample code

      【讨论】:

      • 此文件已从苹果开发者库中删除。
      【解决方案5】:

      Gene Myers 使用“SCNetworkReachabilityCreateWithName”为我发布的答案 - 但仅限于模拟器中。在我的设备(带 OS 2.2.1 的 iPod)上,即使对于像“zzz”这样的无意义地址,它也总是返回“主机可达”。

      我是不是误会了什么?谢谢。

      这是我的代码以防万一:

      来自How to write a simple Ping method in Cocoa/Objective-C

          - (IBAction) TestReachability:(id)sender
      {
          bool success = false;
          const char *host_name = [ipAddressText.textcStringUsingEncoding:NSASCIIStringEncoding];
          NSString *imageConnectionSuccess = @"Connected.png";
          NSString *imageConnectionFailed = @"NotConnected.png";
      
          SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL,
                                                                                      host_name);
          SCNetworkReachabilityFlags flags;
          success = SCNetworkReachabilityGetFlags(reachability, &flags);
          bool isAvailable = success && (flags & kSCNetworkFlagsReachable) && 
              !(flags & kSCNetworkFlagsConnectionRequired);
          if (isAvailable)
          {
              NSLog([NSString stringWithFormat: @"'%s' is reachable, flags: %x", host_name, flags]);
              [imageView setImage: [UIImage imageNamed:imageConnectionSuccess]]; 
          }
          else
          {
              NSLog([NSString stringWithFormat: @"'%s' is not reachable", host_name]);
              [imageView setImage: [UIImage imageNamed:imageConnectionFailed]]; 
          }
      }
      

      【讨论】:

        【解决方案6】:

        请注意,模拟器和实际 iPhone 之间存在差异。该模拟器不是像 Android 提供的那样真正的模拟器,它使用 Mac OSX 类来完成大部分功能。

        如果 Mac OSX 和 iPhonew 之间存在差异(例如钥匙串),这尤其糟糕。

        【讨论】:

          【解决方案7】:

          下面的代码似乎是同步工作的:

          const char *hostName = [@"*.com"
                                  cStringUsingEncoding:NSASCIIStringEncoding];
          SCNetworkConnectionFlags flags = 0;
          if (SCNetworkCheckReachabilityByName(hostName, &flags) && flags > 0) {
            NSLog(@"Host is reachable: %d", flags);
          }
          else {
            NSLog(@"Host is unreachable");
          }
          

          注意:SystemConfiguration.framework 是必需的

          【讨论】:

          • 很遗憾,SCNetworkCheckReachabilityByName 现在已被弃用。
          • 8 票和 +bounty 用于完全不解决问题的代码,即 ping/traceroute 但它基本上是 DNS 查找。
          • 该代码不仅被弃用,而且还在查找 DNS
          • “您不能删除这个已接受的答案”。对不起大家! ?
          • SCNetworkReachability 不能很好地指示主机是否在线。在 LAN 情况下,只要有 WiFi 连接,可达性似乎总是​​返回主机可访问,尽管它实际上是一个无效的主机名。
          最近更新 更多