iOS實(shí)現(xiàn)Ping命令

最近在做一個(gè)VPN工具(https://itunes.apple.com/us/app/bigvpn/id1225850922?mt=8),考慮到類似的網(wǎng)絡(luò)工具需要一個(gè)ping功能,即檢測當(dāng)前網(wǎng)絡(luò)環(huán)境和服務(wù)器的連接狀態(tài),像是PC端的命令行工具ping。于是在Apple的官方demo的基礎(chǔ)上進(jìn)行了了封裝,實(shí)現(xiàn)實(shí)時(shí)顯示當(dāng)前網(wǎng)絡(luò)連接服務(wù)器的延遲,實(shí)現(xiàn)比較簡單,如下:


  1. 聲名屬性變量。
          @interface WHPingTester()<SimplePingDelegate>
          {
              NSTimer* _timer;  //不斷發(fā)送ping命令的定時(shí)器
              NSDate* _beginDate;  // 單個(gè)ping 發(fā)送時(shí)的時(shí)間
          }
          @property(nonatomic, strong) SimplePing* simplePing; //Apple的ping工具
          @property(nonatomic, strong) NSMutableArray<WHPingItem*>* pingItems; //WHPingItem表示每一個(gè)ping包,pingItems是以隊(duì)列的形式存儲(chǔ)和刪除
          @end
    
  2. 在開啟ping命令之前必須對(duì)simplePing進(jìn)行相關(guān)設(shè)置:
        self.simplePing = [[SimplePing alloc] initWithHostName:hostName];
        self.simplePing.delegate = self;
        self.simplePing.addressStyle = SimplePingAddressStyleAny;// 網(wǎng)絡(luò)類型
        self.pingItems = [NSMutableArray new];  //初始化緩存
  1. 調(diào)用start方法開啟ping命令:
        [self.simplePing start];

如果該方法成功執(zhí)行,則以下函數(shù)會(huì)被回調(diào)。

        - (void)simplePing:(SimplePing *)pinger didStartWithAddress:(NSData *)address
          {
                _timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(sendPingData) userInfo:nil repeats:YES];  //開啟定時(shí)器,不斷發(fā)送ping包
          }
  1. sendPingData很簡單:
  - (void) sendPingData
{
    [self.simplePing sendPingWithData:nil];  
}
  1. 方法sendPingWithData發(fā)送成功后,以下函數(shù)會(huì)被調(diào)用(回調(diào))
     - (void)simplePing:(SimplePing *)pinger didSendPacket:(NSData *)packet sequenceNumber:(uint16_t)sequenceNumber
{
   WHPingItem* item = [WHPingItem new];
   item.sequence = sequenceNumber;
   [self.pingItems addObject:item];
   
   _beginDate = [NSDate date];
   dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
       if([self.pingItems containsObject:item])
       {
           NSLog(@"超時(shí)---->");
           [self.pingItems removeObject:item];
           if(self.delegate!=nil && [self.delegate respondsToSelector:@selector(didPingSucccessWithTime:withError:)])
           {
               [self.delegate didPingSucccessWithTime:0 withError:[NSError errorWithDomain:NSURLErrorDomain code:111 userInfo:nil]];
           }
       }
   });
}

在該回調(diào)方法里面,我創(chuàng)建了一個(gè)item對(duì)象,表示一個(gè)ping包,將其加入pingItems緩存里。并將開始時(shí)間_beginDate設(shè)置為當(dāng)前的時(shí)間,最后在1.5秒之后檢測緩存里面是否還有還對(duì)象,如果有(解釋見第6點(diǎn)),說明網(wǎng)絡(luò)不通,最后將其從緩存中將其移除。

  1. 如果收到服務(wù)器的反饋包,則以下函數(shù)會(huì)被調(diào)用:
  - (void)simplePing:(SimplePing *)pinger didReceivePingResponsePacket:(NSData *)packet     sequenceNumber:(uint16_t)sequenceNumber
{
    float delayTime = [[NSDate date] timeIntervalSinceDate:_beginDate] * 1000;
    [self.pingItems enumerateObjectsUsingBlock:^(WHPingItem * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        if(obj.sequence == sequenceNumber)
        {
            [self.pingItems removeObject:obj];
        }
    }];
    if(self.delegate!=nil && [self.delegate respondsToSelector:@selector(didPingSucccessWithTime:withError:)])
    {
        [self.delegate didPingSucccessWithTime:delayTime withError:nil];
    }
}

如上,一旦收到反饋包,則按照序號(hào)刪掉緩存里面相應(yīng)的item(包),delayTime則為收到包的時(shí)間與開始時(shí)間之差。


為了方便大家使用,我已經(jīng)將該demo簡單的封裝了一下并上傳到了github,地址:https://github.com/wanghe826/PingTool

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

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

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