需求:
在數(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 標識)
計算當前位置與服務器的距離并選出距離最近的 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庇绽。
獲取地理位置代碼示例如下:
[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"];
- 獲取當前已下載的圖片的大小及圖片總的大泄嘧:
- 使用
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;
- 當
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]];
}
- 啟動定時器,計算下載速度舅桩,并旋轉指針:
- 將
receivedSize
存儲在數(shù)組arrSpeed
中酱虎,用于計算接收文件的差值。
[self.arrSpeed addObject:[NSNumber numberWithInteger:self.receivedSizes]];
- 獲取數(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]];
- 調用
SpeedTestTool
類中- (NSString *)showSpeedTextWithMB:(double)MB isRealNetSpeed:(BOOL)isRealNetSpeed;
方法獲取顯示在 label 上的速度的字符串撒妈。
NSString *showSpeed = [self.speedTool showSpeedTextWithMB:speedMB / 8 isRealNetSpeed:NO];
self.labSpeed.text = showSpeed;
- 獲取數(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);
}