21

I need to write a simple ping method in Cocoa/Objective-C. It also needs to work on the iPhone.

I found an example that uses icmp, will this work on the iPhone?

I'm leaning towards a solution using NSNetServices, is this a good idea?

The method only needs to ping a few times and return the average and -1 if the host is down or unreachable.

Richard Stelling
  • 25,607
  • 27
  • 108
  • 188

7 Answers7

37

NOTE- I would recommend Chris' solution below which actually answers the question asked, directly. This post from 12 years ago was in response to the original authors upvoted answer, to which I had a better solution. As the author upvoted the answer above that used Reachability, I assumed that he was in fact more interested in reachability than actually in sending a ping, hence my answer. Please consider this before downvoting this answer.

StreamSCNetworkCheckReachabilityByName is deprecated and NOT available for the iPhone. Note: SystemConfiguration.framework is required

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");
}
Gene Myers
  • 1,230
  • 1
  • 14
  • 31
  • Hi. Excelent code and helpful, but only one thing. You require add the code `CFRelease(reachability)` after call `SCNetworkReachabilityGetFlags` to release reachability variable (to prevent memory leaks) as is mentioned in [documentation](https://developer.apple.com/reference/systemconfiguration/1514904-scnetworkreachabilitycreatewithn?language=objc) – Carlos Guzman Oct 23 '16 at 14:47
  • 2
    `SCNetworkReachabilityGetFlags` is a poor substitute of ping – if the device is connected to a network, `kSCNetworkFlagsReachable` will be set and `kSCNetworkFlagsConnectionRequired` will be unset even though the target host is offline. – adib Feb 14 '17 at 13:45
  • I was improving on the accepted answer. I don't debate that SCNetworkReachabilityGetFlags is a poor substitute for 'ping', but if you are just trying to determine reachability, as was rjstelling objective, then this is a fine solution. If you need to monitor latency or provide a heartbeat, then a 'ping' solution is arguably better. – Gene Myers Feb 14 '17 at 13:51
32

I had this same problem, and ended up writing a simple wrapper around SimplePing to achieve this, wrote a blog about it and there's some code on github, hopefully will help someone here:

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

Chris
  • 39,719
  • 45
  • 189
  • 235
13

You are not missing anything -- "Reachability" doesn't actually test that the target domain is in fact reachable, it only assesses if there is a pathway out of the machine by which the target domain is potentially reachable. So long as you have some outbound connection (e.g., an active wirless or wired connection), and a routing configuration that leads to the target, then the site is "reachable" as far as SCNetworkReachability is concerned.

Zhami
  • 19,033
  • 14
  • 48
  • 47
5

Pinging on the iPhone works a bit different than on other platforms, due to the fact that you don't have root access. See this sample code from Apple.

Monobono
  • 780
  • 10
  • 24
0

The answer Gene Myers posted works using "SCNetworkReachabilityCreateWithName" for me - but only in the simulator. On my device (iPod w/OS 2.2.1) it always returns "Host is reachable" even for nonsense addresses like "zzz".

Am I misunderstanding something? Thanks.

Here's my code just in case:

From 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]]; 
    }
}
Community
  • 1
  • 1
Chris Bennet
  • 587
  • 5
  • 13
-1

Please take note that there is an difference between the simulator and the actual iPhone. The simulator is not a true simulator like the one supplied by Android, it uses Mac OSX classes for most of the functions.

This is particularly hell if there is a difference between the Mac OSX and iPhonew(for example the keychain).

Jark
  • 3
  • 2
-8

The code below seems to be working synchronously:

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");
}

Note: SystemConfiguration.framework is required

Vadim
  • 9,383
  • 7
  • 36
  • 58
  • 3
    Unfortunately, SCNetworkCheckReachabilityByName is now deprecated. – William Remacle Oct 12 '10 at 10:30
  • 30
    8 votes and +bounty for code that totally doesn't do what question was about, i.e. ping/traceroute but it's a DNS lookup, basically. – bestsss Oct 26 '11 at 08:10
  • The code is not only deprecated but also looking up the DNS – Adro Aug 06 '15 at 06:45
  • 1
    “You cannot delete this accepted answer”. Sorry guys! – Vadim Aug 11 '15 at 13:33
  • 1
    `SCNetworkReachability` is a poor indicator of whether a host is online. On a LAN situation, reachability seems to always returns that the host is reachable whenever there is a WiFi connection although it's really an invalid host name. – adib Feb 14 '17 at 12:29