How to write a simple Ping method in Cocoa/Objective-C
Asked Answered
H

7

22

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.

Homogeneity answered 28/4, 2009 at 15:7 Comment(0)
R
-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

Remainder answered 16/6, 2009 at 23:7 Comment(5)
Unfortunately, SCNetworkCheckReachabilityByName is now deprecated.Brittaneybrittani
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.Caphaitien
The code is not only deprecated but also looking up the DNSMeeker
“You cannot delete this accepted answer”. Sorry guys! 😃Remainder
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.Monah
M
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");
}
Malevolent answered 5/7, 2009 at 23:37 Comment(3)
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 documentationAuden
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.Monah
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.Malevolent
K
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

Kussell answered 27/1, 2012 at 5:44 Comment(2)
Upvote for a solution that actually answers the question (vs all this useless Reachability stuff which people seem to like but which is totally not addressing the question asked!). Thank you!Lenard
Yes, this is the actual answer.Ocular
B
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.

Benzene answered 8/11, 2009 at 22:16 Comment(0)
K
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.

Kingsbury answered 26/4, 2010 at 19:56 Comment(1)
This file is removed from all around apple developer library.Dogger
R
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]]; 
    }
}
Ranice answered 13/8, 2009 at 12:48 Comment(0)
C
-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).

Comitia answered 19/10, 2009 at 14:25 Comment(0)
R
-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

Remainder answered 16/6, 2009 at 23:7 Comment(5)
Unfortunately, SCNetworkCheckReachabilityByName is now deprecated.Brittaneybrittani
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.Caphaitien
The code is not only deprecated but also looking up the DNSMeeker
“You cannot delete this accepted answer”. Sorry guys! 😃Remainder
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.Monah

© 2022 - 2024 — McMap. All rights reserved.