要在 VC++ 客户端中统计下载的网速,可以在下载过程中记录已下载的字节数和所用的时间。可以使用 `std::chrono` 库来测量时间,并在每次读取数据后计算当前的下载速度。
以下是修改后的代码示例,添加了下载速度的统计功能:
```cpp
#include <windows.h>
#include <winhttp.h>
#include <iostream>
#include <fstream>
#include <chrono>
#include <thread>
#pragma comment(lib, "winhttp.lib")
void DownloadFile(const std::wstring& server, const std::wstring& filePath, const std::wstring& savePath, int speedLimit) {
HINTERNET hSession = WinHttpOpen(L"A WinHTTP Example Program/1.0",
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
WINHTTP_NO_PROXY_NAME,
WINHTTP_NO_PROXY_BYPASS, 0);
if (!hSession) {
std::cerr << "WinHttpOpen failed." << std::endl;
return;
}
HINTERNET hConnect = WinHttpConnect(hSession, server.c_str(), INTERNET_DEFAULT_HTTP_PORT, 0);
if (!hConnect) {
std::cerr << "WinHttpConnect failed." << std::endl;
WinHttpCloseHandle(hSession);
return;
}
HINTERNET hRequest = WinHttpOpenRequest(hConnect, L"GET", filePath.c_str(),
NULL, WINHTTP_NO_REFERER,
WINHTTP_DEFAULT_ACCEPT_TYPES, 0);
if (!hRequest) {
std::cerr << "WinHttpOpenRequest failed." << std::endl;
WinHttpCloseHandle(hConnect);
WinHttpCloseHandle(hSession);
return;
}
// 发送请求
if (!WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0,
WINHTTP_NO_REQUEST_DATA, 0, 0, 0)) {
std::cerr << "WinHttpSendRequest failed." << std::endl;
WinHttpCloseHandle(hRequest);
WinHttpCloseHandle(hConnect);
WinHttpCloseHandle(hSession);
return;
}
// 等待响应
if (!WinHttpReceiveResponse(hRequest, NULL)) {
std::cerr << "WinHttpReceiveResponse failed." << std::endl;
WinHttpCloseHandle(hRequest);
WinHttpCloseHandle(hConnect);
WinHttpCloseHandle(hSession);
return;
}
// 打开文件以写入
std::ofstream outFile(savePath, std::ios::binary);
if (!outFile.is_open()) {
std::cerr << "Failed to open file for writing." << std::endl;
WinHttpCloseHandle(hRequest);
WinHttpCloseHandle(hConnect);
WinHttpCloseHandle(hSession);
return;
}
// 读取数据并写入文件
DWORD bytesRead;
char buffer[4096]; // 4KB 缓冲区
long long totalBytesRead = 0; // 总共读取的字节数
auto startTime = std::chrono::high_resolution_clock::now(); // 开始时间
while (true) {
if (!WinHttpReadData(hRequest, buffer, sizeof(buffer), &bytesRead) || bytesRead == 0) {
break; // 读取完成或出错
}
outFile.write(buffer, bytesRead);
totalBytesRead += bytesRead;
// 限制速度
std::this_thread::sleep_for(std::chrono::milliseconds(1000 * bytesRead / speedLimit)); // 限速
// 计算并输出下载速度
auto currentTime = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> elapsed = currentTime - startTime;
if (elapsed.count() > 0) {
double speed = (totalBytesRead / 1024.0) / elapsed.count(); // KB/s
std::cout << "当前下载速度: " << speed << " KB/s" << std::endl;
}
}
// 关闭文件
outFile.close();
// 清理
WinHttpCloseHandle(hRequest);
WinHttpCloseHandle(hConnect);
WinHttpCloseHandle(hSession);
std::cout << "文件下载成功: " << savePath << std::endl;
}
int main() {
std::wstring server = L"localhost"; // 替换为你的服务器地址
std::wstring filePath = L"/download"; // 替换为下载路径
std::wstring savePath = L"C:\\path\\to\\save\\file.zip"; // 替换为保存路径
int speedLimit = 50 * 1024; // 限制速度为 50 KB/s
DownloadFile(server, filePath, savePath, speedLimit);
return 0;
}
```
### 代码说明
1. **总字节数**:使用 `long long totalBytesRead` 变量来跟踪已读取的总字节数。
2. **开始时间**:在开始下载时记录开始时间。
3. **计算速度**:在每次读取数据后,计算经过的时间,并根据已读取的字节数计算下载速度(单位为 KB/s)。
4. **输出速度**:在控制台输出当前下载速度。
### 注意事项
- 你可以根据需要调整限速值。
- 计算速度的逻辑可以根据需要进行优化,例如每隔一定时间输出一次速度,而不是每次读取数据后都输出。
通过这种方式,你可以在下载过程中实时监控下载速度。


被折叠的 条评论
为什么被折叠?



