網(wǎng)絡測速步驟

需求:
在數(shù)據(jù)中獲取 5 個離當前位置最近的服務器作為目標服務器進行網(wǎng)絡測速龄毡。以測試圖片下載速度的形式對下行網(wǎng)速進行模擬測速,以上傳一個隨機 1M文件速度對上行速度進行模擬測速驱闷;共計 25 秒道伟。該篇文章以測試一個服務器為例模擬網(wǎng)絡測速過程。

demo 鏈接:https://share.weiyun.com/56sSBhy

一瓦糕、解析 XML 格式 數(shù)據(jù)

  • 解析數(shù)據(jù)獲取服務器列表:
    解析網(wǎng)址數(shù)據(jù),并獲取 <servers> 標簽下的 server 列表(即獲取所有的服務器)腋么。
    每一條 <server>數(shù)據(jù)中包含url(服務器地址)咕娄、lat(緯度)、lon(經(jīng)度)珊擂、name(名字)圣勒、sponsor(主辦者)、id(id 標識)

    serversList.png
    圖片網(wǎng)址:https://share.weiyun.com/5qd6KB6

  • 計算當前位置與服務器的距離并選出距離最近的 5 個服務器:
    獲取每一個服務器的經(jīng)度(lon)和緯度(lat)摧扇,并通過SpeedTestTool類中的方法- (void)speedCalculateDistanceWithViewController:(UIViewController *)viewController longitude:(double)longitude latitude:(double)latitude distanceBlock:(DistanceBlock)distanceBlock;計算出該服務器與當前位置的距離圣贸,找出離當前位置最近的 5 個服務器分別為 s1、s2扳剿、s3旁趟、s4、s5庇绽。

serverData.png
圖片網(wǎng)址:https://share.weiyun.com/5xfIjC8

獲取地理位置代碼示例如下:

[self.speedTool speedCalculateDistanceWithViewController:self longitude:116.3917 latitude:39.9139 distanceBlock:^(double distance, CLLocation * _Nonnull currentLocation) {
     NSLog(@"%f,%f,%f",currentLocation.coordinate.longitude,currentLocation.coordinate.latitude,distance);
}];

二锡搜、獲取網(wǎng)絡延遲

  • 獲取主機地址:
    使用SpeedTestTool類中- (NSString *)speedCutOutUrlString:(NSString *)urlString;方法獲取 s1、s2瞧掺、s3耕餐、s4、s5 這5 個服務器url標簽中的主機地址辟狈。

    例:url "http://www2.unicomtest.com:80/speedtest/upload.php"調用這個方法后獲取的主機地址就為www2.unicomtest.com肠缔。

    獲取主機地址示例代碼如下:


NSString *strUrl = @"http://nmgspeedtest1.ffcs.cn:80/speedtest/upload.jsp";
NSString *mainframe = [self.speedTool speedCutOutUrlString:strUrl];

  • 獲取 s1夏跷、s2、s3明未、s4槽华、s5 這5 個服務器的平均網(wǎng)絡延遲:
    通過STDPingServices類中
    + (STDPingServices *)startPingAddress:(NSString *)address callbackHandler:(void(^)(STDPingItem *item, NSArray *pingItems))handler;方法獲取 s1、s2趟妥、s3猫态、s4、s5 這5 個服務器的網(wǎng)絡延遲披摄。每一個服務器獲取 5 次網(wǎng)絡延遲亲雪,計算這個服務器的平均網(wǎng)絡延遲,依照這樣的方法計算剩下 4 個服務器的平均網(wǎng)絡延遲疚膊,最后取得 5 個服務器的平均網(wǎng)絡延遲最為最終的網(wǎng)絡延遲义辕。
    獲取網(wǎng)絡延遲代碼示例如下:
    //獲取網(wǎng)絡延遲
    self.pingServices = [STDPingServices startPingAddress:@"www2.unicomtest.com" callbackHandler:^(STDPingItem *pingItem, NSArray *pingItems) {
        if (pingItem.status != STDPingStatusFinished) {
            NSLog(@"網(wǎng)絡延遲  %.0fms", pingItem.timeMilliseconds);
        }else {
            //NSLog(@"%@", [STDPingItem statisticsWithPingItems:pingItems]);
        }
    }];

三、測試下載速度

  • 獲取測速圖片的 url:
    使用SpeedTestTool類中- (NSString *)changeImageUrlStringWithServerUrlString:(NSString *)urlString;方法獲取即將測試下載速度的圖片 url寓盗。

    例:url http://www2.unicomtest.com:80/speedtest/upload.php 調用這個方法后獲取的下載圖片的 url 為http://www2.unicomtest.com:80/speedtest/random1000x1000.jpg

    獲取圖片 url 示例代碼如下:

 NSString *imgUrlString = [self.speedTool changeImageUrlStringWithServerUrlString:@"http://www2.unicomtest.com:80/speedtest/upload.php"];

  • 獲取當前已下載的圖片的大小及圖片總的大泄嘧:
  1. 使用 SDWebImage三方庫中- (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder options:(SDWebImageOptions)options progress:(nullable SDWebImageDownloaderProgressBlock)progressBlock completed:(nullable SDExternalCompletionBlock)completedBlock; 方法,在 progressBlock 中獲取圖片的下載進度(receivedSize贞让,用于計算網(wǎng)速) 和 圖片大小( expectedSize周崭,用于判斷圖片是否下載完成),并將這兩個值賦給全局變量喳张。
self.receivedSizes = receivedSize;
self.expectedSizes = expectedSize;
  1. receivedSize == expectedSize && expectedSize != 0的時候證明當前圖片已經(jīng)下載完成续镇,可以進行下一個服務器的下載速度測試或進行上傳測試或停止測試。
 if (receivedSize == expectedSize && receivedSize != 0)
{
    [self scheduleFinish];
}

*注:方法中 options 的參數(shù)應為SDWebImageRefreshCached销部,這是為了避免當圖片已經(jīng)下載時 SDWebImage 直接調用緩存中圖片的情況摸航。

整體代碼如下:

- (void)monitorDownloadSpeed
{
    NSString *imgUrlString = [self.speedTool changeImageUrlStringWithServerUrlString:@"http://www2.unicomtest.com:80/speedtest/upload.php"];
    
    UIImageView *img = [[UIImageView alloc] init];
    
    [img sd_setImageWithURL:[NSURL URLWithString:imgUrlString] placeholderImage:nil options:SDWebImageRefreshCached progress:^(NSInteger receivedSize, NSInteger expectedSize, NSURL * _Nullable targetURL) {
        
        self.receivedSizes = receivedSize;
        self.expectedSizes = expectedSize;
        
        if (receivedSize == expectedSize && receivedSize != 0)
        {
            [self scheduleFinish];
        }
    } completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) {
        
        NSLog(@"%ld",cacheType);
        NSLog(@"%@",error);
    }];
}

- (void)scheduleFinish
{
    double sumSpeed = 0.0;
    double lastSpeed = ((NSNumber *)self.arrNetSpeed.lastObject).doubleValue;
    
    [self.timer invalidate];
    self.timer = nil;
    
    [self.arrNetSpeed removeObjectAtIndex:0];
    
    for (NSInteger speed = 0; speed < self.arrNetSpeed.count; speed++)
    {
        sumSpeed += ((NSNumber *)self.arrNetSpeed[speed]).doubleValue;
    }
    
    dispatch_async(dispatch_get_main_queue(), ^{
        
        [self.netSpeedView beginAnimationWithStartValueMbps:lastSpeed endValueMbps:0.0 animationKey:Animation_Key animationValue:Animation_Value];
        self.labSpeed.text = [NSString stringWithFormat:@"%.2fMb/s",(sumSpeed / self.arrNetSpeed.count)];
        
        [self clearAllData];    //這個操作必須在主線程上,否則可能會出現(xiàn)數(shù)據(jù)在子線程上操作提前被清空的情況
    });
}

//清空數(shù)組
- (void)clearAllData
{
    self.receivedSizes = 0;
    self.expectedSizes = 0;
    [self.arrSpeed removeAllObjects];
    [self.arrNetSpeed removeAllObjects];
    [self.arrSpeed addObject:[NSNumber numberWithDouble:0.0]];
    [self.arrNetSpeed addObject:[NSNumber numberWithDouble:0.0]];
}
  • 啟動定時器,計算下載速度舅桩,并旋轉指針:
  1. receivedSize 存儲在數(shù)組 arrSpeed 中酱虎,用于計算接收文件的差值。
[self.arrSpeed addObject:[NSNumber numberWithInteger:self.receivedSizes]];

  1. 獲取數(shù)組 arrSpeed 中最后一個值(speed2) 和 倒數(shù)第二個值(speed1) 擂涛,使用SpeedTestTool 類中- (double)currentSpeedUnitConvertWithByets:(double)bytes isRealNetSpeed:(BOOL)isRealNetSpeed;方法計算速度 (speedMB)读串,并將speedMB存入arrNetSpeed 數(shù)組中。
//獲取接收文件的差值
NSInteger speed2 = ((NSNumber *)self.arrSpeed.lastObject).integerValue;
NSInteger speed1 = ((NSNumber *)self.arrSpeed[self.arrSpeed.count - 2]).integerValue;
//當前速度
double speedMB = [self.speedTool currentSpeedUnitConvertWithByets:((double)speed2 - speed1) isRealNetSpeed:NO];
[self.arrNetSpeed addObject:[NSNumber numberWithDouble:speedMB]];

  1. 調用 SpeedTestTool 類中 - (NSString *)showSpeedTextWithMB:(double)MB isRealNetSpeed:(BOOL)isRealNetSpeed;方法獲取顯示在 label 上的速度的字符串撒妈。
NSString *showSpeed = [self.speedTool showSpeedTextWithMB:speedMB / 8 isRealNetSpeed:NO];
self.labSpeed.text = showSpeed;

  1. 獲取數(shù)組 arrNetSpeed 中最后一個值(netSpeed2) 和 倒數(shù)第二個值(netSpeed1)恢暖,計算兩個速度之間的差值,并旋轉指針狰右。
double netSpeed2 = ((NSNumber *)self.arrNetSpeed.lastObject).doubleValue;
double netSpeed1 = ((NSNumber *)self.arrNetSpeed[self.arrNetSpeed.count - 2]).doubleValue;
        
[self.netSpeedView beginAnimationWithStartValueMbps:netSpeed1 endValueMbps:netSpeed2 animationKey:Animation_Key animationValue:Animation_Value];

整體代碼如下:

- (void)Timered:(NSTimer *)timer
{
    if (self.receivedSizes != 0)
    {
        [self.arrSpeed addObject:[NSNumber numberWithInteger:self.receivedSizes]];
        
        //獲取接收文件的差值
        NSInteger speed2 = ((NSNumber *)self.arrSpeed.lastObject).integerValue;
        NSInteger speed1 = ((NSNumber *)self.arrSpeed[self.arrSpeed.count - 2]).integerValue;
        //當前速度
        double speedMB = [self.speedTool currentSpeedUnitConvertWithByets:((double)speed2 - speed1) isRealNetSpeed:NO];
        
        NSLog(@"%f",speedMB);
        
        //顯示的速度
        NSString *showSpeed = [self.speedTool showSpeedTextWithMB:speedMB / 8 isRealNetSpeed:NO];
        self.labSpeed.text = showSpeed;
        
        //計算兩個速度之間的差值,為動畫旋轉做準備
        [self.arrNetSpeed addObject:[NSNumber numberWithDouble:speedMB]];
        double netSpeed2 = ((NSNumber *)self.arrNetSpeed.lastObject).doubleValue;
        double netSpeed1 = ((NSNumber *)self.arrNetSpeed[self.arrNetSpeed.count - 2]).doubleValue;
        
        [self.netSpeedView beginAnimationWithStartValueMbps:netSpeed1 endValueMbps:netSpeed2 animationKey:Animation_Key animationValue:Animation_Value];
    }
}

三杰捂、測試上傳速度

上傳速度和下載速度的定時器方法大致一樣,這里只介紹測試上傳速度的流程及如何監(jiān)測上傳進度棋蚌。

  • 獲取隨機數(shù):
    使用SpeedTestTool 類中 - (double)getRandomNumber;方法獲取隨機數(shù)嫁佳,以便拼接測試上傳速度的網(wǎng)址挨队。
double randomNum = [self.speedTool getRandomNumber];
NSString *requestUrl = [NSString stringWithFormat:@"%@?r=%f",serverUrl,randomNum];

  • 生成上傳文件:
    生成一個上傳文件,文件可以是 image 類型蒿往,也可以是其他文件類型盛垦,這里以 1 個 1M 大小的圖片為例:
NSData *data = UIImageJPEGRepresentation([UIImage imageNamed:@"img_upload"], 1.0f);
NSString *encodedImageStr = [data base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];

  • 上傳文件:
    上傳文件:
[CSDA_DataHelperUserInfo asynchronousPOSTWithURLString:requestUrl delegate:self bodyString:encodedImageStr PassBlock:^(NSData *data) {
        
} error:^(NSError *error) {
      NSLog(@"%@",error);
}];
  • 監(jiān)測上傳進度:
    如果使用的是系統(tǒng)方法,則需要調用系統(tǒng)方法的上傳熄浓;如使用第三方情臭,自行調用第三方監(jiān)測方法:
//監(jiān)測進度
- (void)URLSession:(NSURLSession *)session task:(nonnull NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend
{
    NSLog(@"%lld",totalBytesSent);
}

整體代碼如下:

- (void)monitorUploadSpeed
{
    NSString *serverUrl = @"http://www2.unicomtest.com:80/speedtest/upload.php";
    double randomNum = [self.speedTool getRandomNumber];
    NSString *requestUrl = [NSString stringWithFormat:@"%@?r=%f",serverUrl,randomNum];
    //圖片轉成 string
    NSData *data = UIImageJPEGRepresentation([UIImage imageNamed:@"img_upload"], 1.0f);
    NSString *encodedImageStr = [data base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
    
    [CSDA_DataHelperUserInfo asynchronousPOSTWithURLString:requestUrl delegate:self bodyString:encodedImageStr PassBlock:^(NSData *data) {
        
    } error:^(NSError *error) {
        NSLog(@"%@",error);
    }];
}

//監(jiān)測進度
- (void)URLSession:(NSURLSession *)session task:(nonnull NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend
{
    NSLog(@"%lld",totalBytesSent);
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市赌蔑,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌竟秫,老刑警劉巖娃惯,帶你破解...
    沈念sama閱讀 206,602評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異肥败,居然都是意外死亡趾浅,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評論 2 382
  • 文/潘曉璐 我一進店門馒稍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來皿哨,“玉大人,你說我怎么就攤上這事纽谒≈づ颍” “怎么了?”我有些...
    開封第一講書人閱讀 152,878評論 0 344
  • 文/不壞的土叔 我叫張陵鼓黔,是天一觀的道長央勒。 經(jīng)常有香客問我,道長澳化,這世上最難降的妖魔是什么崔步? 我笑而不...
    開封第一講書人閱讀 55,306評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮缎谷,結果婚禮上井濒,老公的妹妹穿的比我還像新娘。我一直安慰自己列林,他們只是感情好瑞你,可當我...
    茶點故事閱讀 64,330評論 5 373
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著席纽,像睡著了一般捏悬。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上润梯,一...
    開封第一講書人閱讀 49,071評論 1 285
  • 那天过牙,我揣著相機與錄音甥厦,去河邊找鬼。 笑死寇钉,一個胖子當著我的面吹牛刀疙,可吹牛的內容都是我干的。 我是一名探鬼主播扫倡,決...
    沈念sama閱讀 38,382評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼谦秧,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了撵溃?” 一聲冷哼從身側響起疚鲤,我...
    開封第一講書人閱讀 37,006評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎缘挑,沒想到半個月后集歇,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,512評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡语淘,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,965評論 2 325
  • 正文 我和宋清朗相戀三年诲宇,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片惶翻。...
    茶點故事閱讀 38,094評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡姑蓝,死狀恐怖,靈堂內的尸體忽然破棺而出吕粗,到底是詐尸還是另有隱情纺荧,我是刑警寧澤,帶...
    沈念sama閱讀 33,732評論 4 323
  • 正文 年R本政府宣布溯泣,位于F島的核電站虐秋,受9級特大地震影響,放射性物質發(fā)生泄漏垃沦。R本人自食惡果不足惜客给,卻給世界環(huán)境...
    茶點故事閱讀 39,283評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望肢簿。 院中可真熱鬧靶剑,春花似錦、人聲如沸池充。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽收夸。三九已至坑匠,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間卧惜,已是汗流浹背厘灼。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評論 1 262
  • 我被黑心中介騙來泰國打工夹纫, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人设凹。 一個月前我還...
    沈念sama閱讀 45,536評論 2 354
  • 正文 我出身青樓舰讹,卻偏偏與公主長得像,于是被迫代替她去往敵國和親闪朱。 傳聞我的和親對象是個殘疾皇子月匣,可洞房花燭夜當晚...
    茶點故事閱讀 42,828評論 2 345