以下是完整的工作示例,它只 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 还使用主机,这将阻塞您的主线程,因此在单独的线程中调用它可能很有用。