基本原理是访问稳定的网页来测试速度,或者利用稳定的下载地址来测速,比如 QQ.EXE。两种方案各有优劣:通过网页测速粒度小,但测试无法通过下载地址,而后者更稳定、更准确。

界面由 MFC 完成,网络请求 API 使用 CURL。

HttpClient.cpp

#include "stdafx.h"
                
                #include"HttpClient.h"
                #include "HttpRequest.h"
                #include "HttpRespone.h"
                #include "curl.h"
                #include <stdio.h>
                #include <iostream>
                
                using namespace std;
                
                static int write_data(void *buffer, size_t size, size_t buffer_size, void *_respone)
                {
                
                	HttpRespone *respone = (HttpRespone*)_respone;
                
                
                	HttpRequest*request = respone->getHttpRequest();
                
                	respone->writeData(buffer, buffer_size);
                
                	//request->release();
                
                		const HttpCallBack & x = request->getHttpCallback();
                
                		x(request, respone);
                	return buffer_size;
                }
                
                
                HttpClient* HttpClient::getInstance()
                {
                	static HttpClient*ins = nullptr;
                	if (ins == nullptr)
                	{
                		ins = new HttpClient;
                	}
                	return ins;
                
                }
                
                void HttpClient::doRequest_curl(HttpRequest*request)
                {
                
                	HttpRespone *respone = HttpRespone::create();
                	CURL*easy_handle = curl_easy_init();
                	curl_easy_setopt(easy_handle, CURLOPT_URL, request->getUrl().c_str());
                	curl_easy_setopt(easy_handle, CURLOPT_WRITEFUNCTION, write_data);
                	curl_easy_setopt(easy_handle, CURLOPT_WRITEDATA, respone);
                
                	respone->setHttpRequest(request);
                	request->setCURLhandle(easy_handle);
                
                	// perform
                	auto succ = curl_easy_perform(easy_handle);
                
                
                }
                
                
                void HttpClient::workFunc()
                {
                	while (true)
                	{
                		HttpRequest* request;
                
                		_mutex.lock();
                
                		if (_queue_request.size() <= 0)
                		{
                			_condition.wait(_mutex);
                		}
                		request = _queue_request.front();
                		_queue_request.pop();
                		_mutex.unlock();
                
                		//	log("net thread  %d", _queue_request.size());
                
                		this->doRequest_curl(request);
                
                
                	}
                
                }
                
                void  HttpClient::setTimeoutForConnect(int t)
                {
                	this->_time_connect = t;
                }
                
                void  HttpClient::setTimeoutForRead(int t)
                {
                	this->_time_read = t;
                }
                
                
                HttpClient::HttpClient()
                {
                	this->_time_connect = 5;
                	this->_time_read = 10;
                	curl_global_init(CURL_GLOBAL_WIN32);
                
                	/*auto t = std::thread([=]
                	{
                		this->workFunc();
                	});
                	t.detach();
                	*/
                }
                
                
                
                void HttpClient::send(HttpRequest*request)
                {
                //	request->retain();
                /*	_mutex.lock();
                	_queue_request.push(request);
                	_mutex.unlock();
                
                	_condition.notify_one();
                	*/
                	this->doRequest_curl(request);
                }
                
                HttpClient::~HttpClient()
                {
                	_condition.notify_all();
                }

按钮响应事件


                	int total = 0;
                	int max = 0;
                	int min = 0xffffff;
                
                	char s[500];
                
                	for (int i = 0; i < 10; i++)
                	{
                		int sp = download();
                
                		total += sp;
                		sprintf(s, "%d KB/s", sp);
                
                		_txt_current.SetWindowTextW(toUnicode(s));
                		_size_total = 0;
                
                		sprintf(s, "%d KB/s", total / (i + 1));
                
                		_txt_total.SetWindowTextW(toUnicode(s));
                
                		if (sp > max)
                		{
                			max = sp;
                			sprintf(s, "%d KB/s", max);
                			_txt_max.SetWindowTextW(toUnicode(s));
                		}
                
                		if (sp < min)
                		{
                			min = sp;
                			sprintf(s, "%d KB/s", min);
                			_txt_min.SetWindowTextW(toUnicode(s));
                		}
                	}
                
                	sprintf(s, "0 KB/s");
                	_txt_current.SetWindowTextW(toUnicode(s));
                	MessageBox(_T("测速完成"), _T("完成"), MB_OK);

download 函数


                static int download()
                {
                	CURL *curl;
                	CURLcode res;
                	struct FtpFile ftpfile = {
                		"1.exe",
                		NULL
                	};
                
                	curl = curl_easy_init();
                
                	int t = clock();
                
                	if (curl) {
                
                		//http://www.winrar.com.cn/download/wrar531scp.exe
                
                		curl_easy_setopt(curl, CURLOPT_URL, "http://www.qq.com");
                		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite);,
                		curl_easy_setopt(curl, CURLOPT_WRITEDATA, &ftpfile);
                		curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
                
                		//	curl_easy_setopt(curl, CURLOPT_USERPWD, "SUREN:SUREN");
                
                		t1 = clock();
                		res = curl_easy_perform(curl);
                		curl_easy_cleanup(curl);
                	}
                
                	if (ftpfile.stream)
                	{
                		fclose(ftpfile.stream);
                	}
                
                	//	log("1.txt", "     %d S   %d KB/S    %d KB", (clock() - t), _size_total/(clock() - t), _size_total / 1024);
                
                	return _size_total / (clock() - t);
                
                }