|
VC++实现SOCKET传递限速,比如限制1M/S,不管多少个连接,总传递速率不超过1M/S
在VC++中实现SOCKET传输总速率限制(如1MB/s),可以通过令牌桶算法或滑动窗口控制。以下是完整实现方案:
### 核心方案:令牌桶算法
```cpp
#include <windows.h>
#include <vector>
class RateLimiter {
private:
CRITICAL_SECTION cs;
DWORD lastUpdateTime;
double tokens; // 当前令牌数(字节)
double rate; // 速率(字节/毫秒)
double capacity; // 桶容量(字节)
public:
RateLimiter(double ratePerSec, double burstSize) {
InitializeCriticalSection(&cs);
lastUpdateTime = GetTickCount();
rate = ratePerSec / 1000.0; // 转换为毫秒级
capacity = burstSize;
tokens = burstSize;
}
~RateLimiter() {
DeleteCriticalSection(&cs);
}
bool consume(int bytes) {
EnterCriticalSection(&cs);
DWORD now = GetTickCount();
DWORD elapsed = now - lastUpdateTime;
lastUpdateTime = now;
// 添加新令牌
tokens += elapsed * rate;
if (tokens > capacity) tokens = capacity;
// 检查是否有足够令牌
if (tokens >= bytes) {
tokens -= bytes;
LeaveCriticalSection(&cs);
return true;
}
LeaveCriticalSection(&cs);
return false;
}
};
// 全局限速器(1MB/s,突发2MB)
RateLimiter g_limiter(1024 * 1024, 2 * 1024 * 1024);
```
### SOCKET发送封装(示例)
```cpp
bool SendWithLimit(SOCKET s, const char* buf, int len) {
int sent = 0;
while (sent < len) {
// 计算本次可发送的块大小(不超过MTU)
int chunk = min(len - sent, 1400);
// 等待令牌
while (!g_limiter.consume(chunk)) {
Sleep(5); // 避免CPU忙等待
}
// 实际发送
int ret = send(s, buf + sent, chunk, 0);
if (ret <= 0) return false;
sent += ret;
}
return true;
}
```
### 多连接处理要点
1. **全局共享限速器**:所有连接共享同一个RateLimiter实例
2. **精确时间控制**:使用GetTickCount()或QueryPerformanceCounter
3. **突发处理**:通过capacity参数允许短期突发
### 增强方案
```cpp
// 精确到微秒的版本(需要Windows8+)
class HighPrecisionLimiter {
private:
LARGE_INTEGER freq;
LARGE_INTEGER lastTime;
// ...其他成员相同...
public:
HighPrecisionLimiter(double ratePerSec, double burstSize) {
QueryPerformanceFrequency(&freq);
QueryPerformanceCounter(&lastTime);
// ...初始化其他成员...
}
bool consume(int bytes) {
LARGE_INTEGER now;
QueryPerformanceCounter(&now);
double elapsed = (now.QuadPart - lastTime.QuadPart) * 1000.0 / freq.QuadPart;
lastTime = now;
// ...其余逻辑相同...
}
};
```
### 注意事项
1. 线程安全:所有共享资源访问必须加锁
2. 性能权衡:Sleep时间越长CPU占用越低但精度下降
3. 单位统一:确保所有计算使用相同单位(推荐字节和毫秒)
这种实现可以精确控制所有SOCKET连接的总带宽不超过设定值,同时允许合理的短期突发传输。
|
|