iOS在工程中ping某個(gè)服務(wù)節(jié)點(diǎn)

最近在做項(xiàng)目時(shí)需要個(gè)需求,是需要對(duì)某個(gè)節(jié)點(diǎn)的判斷 連接的ping值和網(wǎng)速,查閱資料時(shí)看到了蘋(píng)果的一個(gè)demo:SimplePing
然后根據(jù)蘋(píng)果的demo寫(xiě)了個(gè)工具判斷網(wǎng)絡(luò)延遲和丟包率

1.蘋(píng)果的demo是定時(shí)器發(fā)送一個(gè)ping,請(qǐng)求會(huì)帶有標(biāo)志sequenceNumber
2.然后在回調(diào)delegate方法里,也會(huì)帶有sequenceNumber,這樣就可以判斷是哪個(gè)請(qǐng)求

我這里用一個(gè)對(duì)象數(shù)組,存儲(chǔ)每次ping的發(fā)送時(shí)間和回調(diào)時(shí)間,在定時(shí)器結(jié)束時(shí)判斷回調(diào)了多少次來(lái)算丟包率,邏輯很簡(jiǎn)單

所以大家有空的話可以自己看蘋(píng)果的demo,自己封裝一個(gè),省事的話可以用我這個(gè)


  • 1.頭文件 在pingTimeLength時(shí)間內(nèi)執(zhí)行pingTimes次ping
@interface MDPing : NSObject

/** ping多長(zhǎng)時(shí)間,默認(rèn)1s */
@property (nonatomic) CGFloat pingTimeLength;

/** ping多少次,默認(rèn)10 */
@property (nonatomic) NSInteger pingTimes;
/**
 開(kāi)啟對(duì)ip點(diǎn)的丟包率和延遲檢測(cè)
 
 @param hostName 檢測(cè)點(diǎn)
 @param callBack 回調(diào)
 */
- (void)startWithHostName:(NSString *)hostName callBack:(void(^)(int pingValue,float lossRate))callBack;
@end
  • 2.開(kāi)始執(zhí)行定時(shí)器輪訓(xùn)ping
    這里我起了個(gè)異步線程,為的是不打擾主線程的UI操作,并且runloop開(kāi)啟線程
    定時(shí)器到固定的時(shí)間后會(huì)清空pinger,線程停止
if (!_workQueue) {
        _workQueue = dispatch_queue_create("ping.workqueue", DISPATCH_QUEUE_CONCURRENT);
    }
    dispatch_async(_workQueue, ^{
        self.callBack = callBack;
        self.pingValus = @[].mutableCopy;
        
        assert(self.pinger == nil);
        
        self.pinger = [[SimplePing alloc] initWithHostName:hostName];
        assert(self.pinger != nil);
        
        if (self.forceIPv4 && ! self.forceIPv6) {
            self.pinger.addressStyle = SimplePingAddressStyleICMPv4;
        } else if (self.forceIPv6 && ! self.forceIPv4) {
            self.pinger.addressStyle = SimplePingAddressStyleICMPv6;
        }
        
        self.pinger.delegate = self;
        [self.pinger start];
        
        do {
            [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
        } while (self.pinger != nil);
    });
  • 3.執(zhí)行定時(shí)器清空和數(shù)據(jù)返回
    didStartWithAddress這個(gè)方法是連接成功后的回調(diào)
- (void)sendPing {
    assert(self.pinger != nil);
    [self.pinger sendPingWithData:nil];
    
    PingValue *value = [PingValue new];
    value.startPingTime = [NSDate date].timeIntervalSince1970;
    [_pingValus addObject:value];
    
    if (_pingValus.count >= _pingTimes) {
        [self.sendTimer invalidate];
        self.sendTimer = nil;
        self.pinger = nil;
    }
}

- (void)simplePing:(SimplePing *)pinger didStartWithAddress:(NSData *)address {
#pragma unused(pinger)
    assert(pinger == self.pinger);
    assert(address != nil);
    
    // Send the first ping straight away.
    
    [self sendPing];
    
    // And start a timer to send the subsequent pings.
    assert(self.sendTimer == nil);
    self.sendTimer = [NSTimer scheduledTimerWithTimeInterval:_pingTimeLength/_pingTimes target:self selector:@selector(sendPing) userInfo:nil repeats:YES];
    
    
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)((_pingTimeLength+0.1) * NSEC_PER_SEC)), dispatch_get_global_queue(0, 0), ^{
        
        [self.sendTimer invalidate];
        self.sendTimer = nil;
        self.pinger = nil;
        
        if (self.callBack) {
            double x = 0;
            int backTimes = 0;
            for (PingValue *value  in self.pingValus) {
                
                if (value.backTime != 0) {
                    x += (value.backTime-value.startPingTime);
                    backTimes ++;
                }
            }
            dispatch_async(dispatch_get_main_queue(), ^{
                self.callBack(x*1000/backTimes, 1-(backTimes/(self.pingValus.count *1.f)));
            });
            
        }
    });
}
  • 4.每次收到ping回調(diào)
- (void)simplePing:(SimplePing *)pinger didReceivePingResponsePacket:(NSData *)packet sequenceNumber:(uint16_t)sequenceNumber {
#pragma unused(pinger)
    assert(pinger == self.pinger);
#pragma unused(packet)
    NSLog(@"#%u received, size=%zu", (unsigned int) sequenceNumber, (size_t) packet.length);
    if (sequenceNumber<_pingValus.count) {
        _pingValus[sequenceNumber].backTime = [NSDate date].timeIntervalSince1970;
    }
    
}

到這里所有的操作的都完成了,我寫(xiě)的很簡(jiǎn)單,基本就是把蘋(píng)果demo拿來(lái)改下

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容