从主机获取ping延迟

我试图从主机得到延迟一个很好的时间,我卡住了。已经尝试简单的Ping ,但似乎不会返回延迟。 我做的最近的是当我使用TKC-PingTest的MAC OS。 这工作完美,但只在iPhone模拟器,因为当使用iPhone我得到一个错误,由于补丁“/ sbin / ping”TKC使用。 除了这两个,我已经尝试了很多,什么也没有。

您可以轻松地扩展简单的ping来计算延迟。 Simpleping.h定义了SimplePingDelegate协议。 有两个有趣的方法 – didSendPacketdidSendPacket 。 一个天真的执行时间延迟将是

 @property (strong,nonatomic) NSDate *start; - (void)simplePing:(SimplePing *)pinger didSendPacket:(NSData *)packet { self.start=[NSDate date]; } - (void)simplePing:(SimplePing *)pinger didReceivePingResponsePacket:(NSData *)packet { NSDate *end=[NSDate date]; double latency = [end timeIntervalSinceDate:self.start]*1000.0; //TODO - Do something with latency } 

我说这是一个niave实现,因为它不处理在收到响应之前发送另一个数据包或丢弃数据包的情况。 要处理这个问题,您需要检查分组数据,以确定发送和接收事件之间的序列号是否一致。

以下是一个完整的工作示例,其中ping了一次给定的地址,然后以毫秒为单位返回ping时间:

Objective-C的

 @interface SimplePingClient : NSObject<SimplePingDelegate> +(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 

示例用法如下:

 [SimplePingClient pingHostname:@"www.apple.com" andResultCallback:^(NSString *latency) { NSLog(@"your latency is: %@", latency ? latency : @"unknown"); }]; 

迅速

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

用法:

 SimplePingClient.pingHostname("www.apple.com") { latency in print("Your latency is \(latency ?? "unknown")") } 

为了方便起见,我使用SimplePing ,正如文档中所述,它与iOS完全兼容:

SimplePing可以在Mac OS X 10.7及更高版本上运行,不过核心代码在所有版本的iOS上都可以正常工作,而底层方法则可以在早期版本的Mac OS X(10.2版本)上运行。

请注意,我正在使用单身,因为我反复检查延迟,但是如果你只需要一次,你可以采用它没有单身实例。 此外SimplePing使用主机,这将阻止您的主线程,所以调用它在单独的线程可能是有用的。

Swift 3实现hris.to的答案:

 import Foundation public typealias SimplePingClientCallback = (String?)->() public class SimplePingClient: NSObject { fileprivate static let singletonPC = SimplePingClient() fileprivate var resultCallback: SimplePingClientCallback? fileprivate var pingClinet: SimplePing? fileprivate var dateReference: Date? public static func pingHostname(hostname: String, andResultCallback callback: SimplePingClientCallback?) { singletonPC.pingHostname(hostname: 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, didSendPacket packet: Data, sequenceNumber: UInt16){ dateReference = Date() } public func simplePing(_ pinger: SimplePing, didStartWithAddress address: Data) { pinger.send(with: nil) } public func simplePing(_ pinger: SimplePing, didFailWithError error: Error) { resultCallback?(nil) } public func simplePing(_ pinger: SimplePing, didReceiveUnexpectedPacket packet: Data) { pinger.stop() resultCallback?(nil) } public func simplePing(_ pinger: SimplePing, didReceivePingResponsePacket packet: Data, sequenceNumber: UInt16) { pinger.stop() guard let dateReference = dateReference else { return } //timeIntervalSinceDate returns seconds, so we convert to milis let latency = Date().timeIntervalSince(dateReference) * 1000 resultCallback?(String(format: "%.f", latency)) } public func simplePing(_ pinger: SimplePing, didFailToSendPacket packet: Data, sequenceNumber: UInt16, error: Error) { pinger.stop() resultCallback?(nil) } }