从主机获取ping延迟

Luc*_*ito 7 latency ping bandwidth objective-c ios

我正试图从主机获得延迟很长时间而且我陷入困境.已经尝试过Simple Ping ,但似乎它没有返回延迟.我最接近的是当我使用TKC-PingTest进行MAC OS时.这是完美的,但仅限于iPhone模拟器,因为当使用iPhone时,我得到一个错误,因为TKC使用了补丁"/ sbin/ping".除了这两个,我已经尝试过很多其他的东西,什么都没有.

hri*_*.to 17

以下是完整的工作示例,它只给出一次给定的地址,然后以毫秒为单位返回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
Run Code Online (Sandbox Code Playgroud)

示例用法如下:

[SimplePingClient pingHostname:@"www.apple.com"
             andResultCallback:^(NSString *latency) {

                 NSLog(@"your latency is: %@", latency ? latency : @"unknown");

             }];
Run Code Online (Sandbox Code Playgroud)

迅速

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))
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

SimplePingClient.pingHostname("www.apple.com") { latency in

            print("Your latency is \(latency ?? "unknown")")
        }
Run Code Online (Sandbox Code Playgroud)

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

SimplePing在Mac OS X 10.7及更高版本上运行,尽管核心代码在所有iOS版本上运行良好,而基础方法适用于早期版本的Mac OS X(返回10.2).

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


Pau*_*w11 8

您可以轻松扩展简单的ping来计算延迟.Simpleping.h定义了SimplePingDelegate协议.有两种感兴趣的方法 - didSendPacketdidReceivePingResponsePacket.对延迟计时的简单实现将是

@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
}
Run Code Online (Sandbox Code Playgroud)

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