I\'m trying to get the latency from host for a pretty good time and I\'m stuck in. Already tried Simple Ping , but seems it doesn\'t return the latency. The closest I\'ve d
Following is full working example which pings exactly once given address and then returns ping time in miliseconds:
Objective-C
@interface SimplePingClient : NSObject
+(void)pingHostname:(NSString*)hostName andResultCallback:(void(^)(NSString* latency))result;
@end
@interface SimplePingClient()
{
SimplePing* _pingClient;
NSDate* _dateReference;
}
@property(nonatomic, strong) void(^resultCallback)(NSString* latency);
@end
@implementation SimplePingClient
+(void)pingHostname:(NSString*)hostName andResultCallback:(void(^)(NSString* latency))result
{
static SimplePingClient* singletonPC = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
singletonPC = [[SimplePingClient alloc] init];
});
//ping hostname
[singletonPC pingHostname:hostName andResultCallBlock:result];
}
-(void)pingHostname:(NSString*)hostName andResultCallBlock:(void(^)(NSString* latency))result
{
_resultCallback = result;
_pingClient = [SimplePing simplePingWithHostName:hostName];
_pingClient.delegate = self;
[_pingClient start];
}
#pragma mark - SimplePingDelegate methods
- (void)simplePing:(SimplePing *)pinger didStartWithAddress:(NSData *)address
{
[pinger sendPingWithData:nil];
}
- (void)simplePing:(SimplePing *)pinger didFailWithError:(NSError *)error
{
_resultCallback(nil);
}
- (void)simplePing:(SimplePing *)pinger didSendPacket:(NSData *)packet
{
_dateReference = [NSDate date];
}
- (void)simplePing:(SimplePing *)pinger didFailToSendPacket:(NSData *)packet error:(NSError *)error
{
[pinger stop];
_resultCallback(nil);
}
- (void)simplePing:(SimplePing *)pinger didReceivePingResponsePacket:(NSData *)packet
{
[pinger stop];
NSDate *end=[NSDate date];
double latency = [end timeIntervalSinceDate:_dateReference] * 1000;//get in miliseconds
_resultCallback([NSString stringWithFormat:@"%.f", latency]);
}
- (void)simplePing:(SimplePing *)pinger didReceiveUnexpectedPacket:(NSData *)packet
{
[pinger stop];
_resultCallback(nil);
}
@end
And example usage is as follows:
[SimplePingClient pingHostname:@"www.apple.com"
andResultCallback:^(NSString *latency) {
NSLog(@"your latency is: %@", latency ? latency : @"unknown");
}];
Swift
import Foundation
public typealias SimplePingClientCallback = (String?)->()
public class SimplePingClient: NSObject {
static let singletonPC = SimplePingClient()
private var resultCallback: SimplePingClientCallback?
private var pingClinet: SimplePing?
private var dateReference: NSDate?
public static func pingHostname(hostname: String, andResultCallback callback: SimplePingClientCallback?) {
singletonPC.pingHostname(hostname, andResultCallback: callback)
}
public func pingHostname(hostname: String, andResultCallback callback: SimplePingClientCallback?) {
resultCallback = callback
pingClinet = SimplePing(hostName: hostname)
pingClinet?.delegate = self
pingClinet?.start()
}
}
extension SimplePingClient: SimplePingDelegate {
public func simplePing(pinger: SimplePing!, didStartWithAddress address: NSData!) {
pinger.sendPingWithData(nil)
}
public func simplePing(pinger: SimplePing!, didFailWithError error: NSError!) {
resultCallback?(nil)
}
public func simplePing(pinger: SimplePing!, didSendPacket packet: NSData!) {
dateReference = NSDate()
}
public func simplePing(pinger: SimplePing!, didFailToSendPacket packet: NSData!, error: NSError!) {
pinger.stop()
resultCallback?(nil)
}
public func simplePing(pinger: SimplePing!, didReceiveUnexpectedPacket packet: NSData!) {
pinger.stop()
resultCallback?(nil)
}
public func simplePing(pinger: SimplePing!, didReceivePingResponsePacket packet: NSData!) {
pinger.stop()
guard let dateReference = dateReference else { return }
//timeIntervalSinceDate returns seconds, so we convert to milis
let latency = NSDate().timeIntervalSinceDate(dateReference) * 1000
resultCallback?(String(format: "%.f", latency))
}
}
Usage:
SimplePingClient.pingHostname("www.apple.com") { latency in
print("Your latency is \(latency ?? "unknown")")
}
Just for convenience I'm using SimplePing which as stated in docs is fully compatible with iOS:
SimplePing runs on Mac OS X 10.7 and later, although the core code works just fine on all versions of iOS and the underlying approach works on earlier versions of Mac OS X (back to 10.2).
Please note that I'm using singleton, as I repeatedly check latency, however if you need this just once you can adopt it without singleton instance. Also SimplePing uses hosts, which will block your main thread so calling it in separate thread might be useful.