赞
踩
限速算法基于令牌桶算法
1)记最大速度单位为S,第一次发送开始时,记当前时间为T,记令牌桶初始化N=0, N最大值为2S,最小发送单位M=S/4,发送间隔I = 200ms
2)发送前记录当前时间为t,如果 S(t-T) + N >= 2S, 令N = 2S, T = t ,发送M数据,休眠I时间
3)发送前记录当前时间为t, 如果 M < S(t-T) + N < 2S,则发送M数据,休眠I时间
4)发送前记录当前时间为t,如果 S(t-T) + N < M, 则使N = N + S(t-T), 休眠I时间
5)如果数据全部发送完毕则结束
#define RATELIMIT_BURST_TIMES_DEFAULT (2) //2s #define RATELIMIT_USLEEP_INTERVAL (200000) //200ms #define RATELIMIT_MINTOKER_DIV_PARAM (4) //division parameter typedef struct _RateLimitInfo { struct timeval StartTime; uint8_t RateLimitBurstTimes; uint64_t MaxSendRateBps; uint64_t RateLimitToken; uint64_t MinRateLimitToken; /* when Token is larger than minToken, then send data of MinRateLimitToken */ uint64_t SleepInterval; uint64_t DataBuffSize; uint64_t DataBuffCount; char DataBuff[0]; }__attribute__((packed)) RateLimitInfo; uint64_t GetRateLimitValuebybps( uint64_t MaxSendRatebps, uint64_t UnitSize ) { uint64_t ret = 0; uint64_t sendRateHostOrder = be64toh(MaxSendRatebps); //net order convert if needed ret = sendRateHostOrder / 8; if (ret % UnitSize > UnitSize / 2) { ret = ret - ret % UnitSize; } else { ret = ret - ret % UnitSize + UnitSize; } if (ret == 0) { ret = UnitSize; } return ret; } uint64_t RateLimitGetMinLimitToken( uint64_t MaxSendRateBps, uint64_t UnitSize ) { uint64_t minRateLimitToken = MaxSendRateBps / RATELIMIT_MINTOKER_DIV_PARAM ; minRateLimitToken = minRateLimitToken + UnitSize - minRateLimitToken % UnitSize; return minRateLimitToken; } int RateLimitInit( uint64_t MaxSendRateBps, uint64_t UnitSize, RateLimitInfo** RateLimit ) { *RateLimit = malloc(sizeof(RateLimitInfo) + 1024 * 1024); if (*RateLimit == NULL) { printf("Malloc memory for Ratelimit error!\n"); return -ENOMEM; } (*RateLimit)->RateLimitBurstTimes = RATELIMIT_BURST_TIMES_DEFAULT; (*RateLimit)->MaxSendRateBps = MaxSendRateBps; (*RateLimit)->DataBuffSize = 1024 * 1024; //1M (*RateLimit)->DataBuffCount = 0; (*RateLimit)->RateLimitToken = 0; (*RateLimit)->SleepInterval = RATELIMIT_USLEEP_INTERVAL; /* MinRateLimitToken as usual , shoule be smaller or equal than DataBuffSize*/ (*RateLimit)->MinRateLimitToken = RateLimitGetMinLimitToken(MaxSendRateBps, UnitSize); gettimeofday(&((*RateLimit)->StartTime), NULL); return 0; } void UpdateRateLimitToken( RateLimitInfo* RateLimit ) { struct timeval currentTime; uint64_t diff = 0; uint64_t tokenAddSize = 0; if (RateLimit->SleepInterval) { usleep(RateLimit->SleepInterval); } gettimeofday(¤tTime, NULL); diff = (currentTime.tv_sec - (RateLimit->StartTime).tv_sec) * 1000 + (currentTime.tv_usec - (RateLimit->StartTime).tv_usec) / 1000; tokenAddSize = diff * RateLimit->MaxSendRateBps / 1000; RateLimit->RateLimitToken = RateLimit->RateLimitToken + tokenAddSize; if (RateLimit->RateLimitToken < RateLimit->MinRateLimitToken) { RateLimit->SleepInterval = RATELIMIT_USLEEP_INTERVAL; goto CommonReturn; } else { memcpy(&RateLimit->StartTime, ¤tTime, sizeof(currentTime)); } CommonReturn: return; } void RateLimitFree(RateLimitInfo* RateLimit) { free(RateLimit); }
使用:
int SendUnitDataWithRateLimit( int Sockfd, RateLimitInfo* RateLimit ) { int ret = 0; int64_t sendSize = 0; for(;;) { UpdateRateLimitToken(RateLimit); while (RateLimit->RateLimitToken >= RateLimit->MinRateLimitToken && RateLimit->RateLimitToken >= Conn->UnitSize) { /*Do your send function*/ sendSize = send_func(SockFd, (char *)RateLimit->DataBuff, RateLimit->RateLimitToken); RateLimit->RateLimitToken -= sendSize; /*Do your exit logic*/ } } CommonReturn: return ret; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。