美文网首页
网络测速步骤

网络测速步骤

作者: 黎明s | 来源:发表于2019-04-28 18:20 被阅读0次

    需求:
    在数据中获取 5 个离当前位置最近的服务器作为目标服务器进行网络测速。以测试图片下载速度的形式对下行网速进行模拟测速,以上传一个随机 1M文件速度对上行速度进行模拟测速;共计 25 秒。该篇文章以测试一个服务器为例模拟网络测速过程。

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

    一、解析 XML 格式 数据

    • 解析数据获取服务器列表:
      解析网址数据,并获取 <servers> 标签下的 server 列表(即获取所有的服务器)。
      每一条 <server>数据中包含url(服务器地址)、lat(纬度)、lon(经度)、name(名字)、sponsor(主办者)、id(id 标识)

      serversList.png 图片网址:https://share.weiyun.com/5qd6KB6
    • 计算当前位置与服务器的距离并选出距离最近的 5 个服务器:
      获取每一个服务器的经度(lon)和纬度(lat),并通过SpeedTestTool类中的方法- (void)speedCalculateDistanceWithViewController:(UIViewController *)viewController longitude:(double)longitude latitude:(double)latitude distanceBlock:(DistanceBlock)distanceBlock;计算出该服务器与当前位置的距离,找出离当前位置最近的 5 个服务器分别为 s1、s2、s3、s4、s5。

    serverData.png 图片网址: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);
    }];
    

    二、获取网络延迟

    • 获取主机地址:
      使用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 个服务器的平均网络延迟:
      通过STDPingServices类中
      + (STDPingServices *)startPingAddress:(NSString *)address callbackHandler:(void(^)(STDPingItem *item, NSArray *pingItems))handler;方法获取 s1、s2、s3、s4、s5 这5 个服务器的网络延迟。每一个服务器获取 5 次网络延迟,计算这个服务器的平均网络延迟,依照这样的方法计算剩下 4 个服务器的平均网络延迟,最后取得 5 个服务器的平均网络延迟最为最终的网络延迟。
      获取网络延迟代码示例如下:
        //获取网络延迟
        self.pingServices = [STDPingServices startPingAddress:@"www2.unicomtest.com" callbackHandler:^(STDPingItem *pingItem, NSArray *pingItems) {
            if (pingItem.status != STDPingStatusFinished) {
                NSLog(@"网络延迟  %.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,用于计算网速) 和 图片大小( expectedSize,用于判断图片是否下载完成),并将这两个值赋给全局变量。
    self.receivedSizes = receivedSize;
    self.expectedSizes = expectedSize;
    
    1. receivedSize == expectedSize && expectedSize != 0的时候证明当前图片已经下载完成,可以进行下一个服务器的下载速度测试或进行上传测试或停止测试。
     if (receivedSize == expectedSize && receivedSize != 0)
    {
        [self scheduleFinish];
    }
    

    *注:方法中 options 的参数应为SDWebImageRefreshCached,这是为了避免当图片已经下载时 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];    //这个操作必须在主线程上,否则可能会出现数据在子线程上操作提前被清空的情况
        });
    }
    
    //清空数组
    - (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 存储在数组 arrSpeed 中,用于计算接收文件的差值。
    [self.arrSpeed addObject:[NSNumber numberWithInteger:self.receivedSizes]];
    
    
    1. 获取数组 arrSpeed 中最后一个值(speed2) 和 倒数第二个值(speed1) ,使用SpeedTestTool 类中- (double)currentSpeedUnitConvertWithByets:(double)bytes isRealNetSpeed:(BOOL)isRealNetSpeed;方法计算速度 (speedMB),并将speedMB存入arrNetSpeed 数组中。
    //获取接收文件的差值
    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. 获取数组 arrNetSpeed 中最后一个值(netSpeed2) 和 倒数第二个值(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];
        }
    }
    

    三、测试上传速度

    上传速度和下载速度的定时器方法大致一样,这里只介绍测试上传速度的流程及如何监测上传进度。

    • 获取随机数:
      使用SpeedTestTool 类中 - (double)getRandomNumber;方法获取随机数,以便拼接测试上传速度的网址。
    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);
    }];
    
    • 监测上传进度:
      如果使用的是系统方法,则需要调用系统方法的上传;如使用第三方,自行调用第三方监测方法:
    //监测进度
    - (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);
        }];
    }
    
    //监测进度
    - (void)URLSession:(NSURLSession *)session task:(nonnull NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend
    {
        NSLog(@"%lld",totalBytesSent);
    }
    

    相关文章

      网友评论

          本文标题:网络测速步骤

          本文链接:https://www.haomeiwen.com/subject/sefdnqtx.html