如何在Cocoa/Objective-C中编写一个简单的Ping方法

21

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

我找到了一个使用icmp的示例,这个方法能在iPhone上使用吗?

我倾向于使用NSNetServices来解决问题,这是一个好主意吗?

该方法只需对目标主机进行ping几次,并返回平均值以及-1(如果主机不可达或无法访问)。

7个回答

37
注意:我建议使用下面Chris的解决方案,该方案直接回答了所提出的问题。12年前的这篇文章是对原始作者被投票赞同的答案的回应,而我有一个更好的解决方案。由于作者赞成使用Reachability的答案,我假设他实际上更关心可达性而不是发送ping,因此给出了我的答案。在您投票之前,请考虑这一点。

StreamSCNetworkCheckReachabilityByName已经过时,并且不适用于iPhone。 注意:需要SystemConfiguration.framework

bool success = false;
const char *host_name = [@"stackoverflow.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)来释放reachability变量(以防止内存泄漏),正如文档中所述。 - Carlos Guzman
2
SCNetworkReachabilityGetFlags是ping的不良替代品 - 如果设备连接到网络,kSCNetworkFlagsReachable将被设置,而kSCNetworkFlagsConnectionRequired将不会被设置,即使目标主机处于离线状态。 - adib
我正在改进已接受的答案。我不争辩SCNetworkReachabilityGetFlags是“ping”的劣质替代品,但如果您只是想确定可达性,就像rjstelling的目标一样,那么这是一个很好的解决方案。如果您需要监视延迟或提供心跳,则“ping”解决方案可能更好。 - Gene Myers

32

14
给一个实际回答问题的解决方案点赞(与所有这些毫无意义的 Reachability 相比,人们似乎喜欢它,但它完全没有回答所提出的问题!)。谢谢! - Bill Patterson
是的,这就是实际答案。 - user623396

13
您没有错过任何东西——“可达性”实际上并不测试目标域名是否确实可达,它只评估是否存在一条路径从机器出去,通过该路径目标域名可能可达。只要您有一些出站连接(例如,一个活动的无线或有线连接)和通向目标的路由配置,则在SCNetworkReachability方面,该站点就是“可达的”。

5

在iPhone上进行ping操作与其他平台有所不同,因为您没有root访问权限。请参阅苹果公司的示例代码


此文件已从苹果开发者库中全部删除。 - ahmet alp balkan

0

Gene Myers 发布的答案对我来说使用 "SCNetworkReachabilityCreateWithName" 能够工作 - 但仅限于模拟器。在我的设备上 (iPod w/OS 2.2.1),即使是像 "zzz" 这样的无意义地址,它始终返回 "主机可达"。

我有什么误解吗?谢谢。

这是我的代码,以防万一:

来自 如何在Cocoa/Objective-C中编写简单的Ping方法

    - (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]]; 
    }
}

-1
请注意模拟器和实际 iPhone 之间存在差异。模拟器不像 Android 提供的真正模拟器那样,它使用 Mac OSX 类来执行大部分功能。
如果 Mac OSX 和 iPhone 之间存在差异(例如钥匙串),这将特别麻烦。

-8
以下代码似乎是同步工作的:
const char *hostName = [@"stackoverflow.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

3
SCNetworkCheckReachabilityByName函数已经被弃用。 - William Remacle
30
为代码提供8票和+悬赏,完全不实现问题所涉及的功能,即进行ping/traceroute但实际上是DNS查询。 - bestsss
代码不仅已被弃用,而且正在查找DNS。 - Adro
1
“您无法删除此已接受的答案”。抱歉! - Vadim
1
SCNetworkReachability并不是判断主机是否在线的好指标。在局域网环境中,当有WiFi连接时,可达性似乎总是返回主机可达的结果,尽管它实际上是一个无效的主机名。 - adib

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接