stone2083

SCP限速逻辑实现--带中文注释的bandwidth_limit函数

SCP限速逻辑实现--带中文注释的bandwidth_limit函数

SCP支持限速, 通过-l参数, 指定拷贝的速度
 -l limit
             Limits the used bandwidth, specified in Kbit/s.

具体实现, 是在misc.c中的bandwidth_limit函数
下面附上带中文注释的bandwidth_limit函数代码
 1 struct bwlimit {
 2     size_t buflen;                 // 每次read的buf长度
 3     u_int64_t rate, thresh, lamt;  // rate:  限速速率, 单位kpbs
 4                                    // thresh:统计周期,read长度到了指定阈值, 触发限速统计
 5                                    // lamt:  一次统计周期内, read了多少长度
 6     struct timeval bwstart, bwend; // bwstart: 统计周期之开始时间
 7                                    // bwend:   统计周期之结束时间
 8 };
 9 
10 void bandwidth_limit_init(struct bwlimit *bw, u_int64_t kbps, size_t buflen)
11 {
12     bw->buflen = buflen;          // 初始化read buf长度
13     bw->rate = kbps;              // 初始化限速速率
14     bw->thresh = bw->rate;        // 初始化统计周期
15     bw->lamt = 0;                 // 初始化当前read长度
16     timerclear(&bw->bwstart);     // 初始化统计开始时间
17     timerclear(&bw->bwend);       // 初始化统计结束时间
18 }
19 
20 void bandwidth_limit(struct bwlimit *bw, size_t read_len)
21 {
22     u_int64_t waitlen;
23     struct timespec ts, rm;
24 
25     // 设置统计开始时间, 为当前时间
26     if (!timerisset(&bw->bwstart)) {
27         gettimeofday(&bw->bwstart, NULL);
28         return;
29     }
30 
31     // 设置当前read长度
32     bw->lamt += read_len;
33     // 判断当前read长度是否到达统计周期的阈值
34     if (bw->lamt < bw->thresh)
35         return;
36 
37     // 设置统计结束时间,为当前时间
38     gettimeofday(&bw->bwend, NULL);
39     // bwend变量复用, 这个时候, bwend含义为, 本次统计周期实际开销的时间: 既read thresh长度字节,花了多少时间.
40     timersub(&bw->bwend, &bw->bwstart, &bw->bwend);
41     if (!timerisset(&bw->bwend))
42         return;
43 
44     // 将单位从Byte变成bit
45     bw->lamt *= 8;
46     // 根据限速速率, 计算理论应该花费多少时间
47     waitlen = (double)1000000L * bw->lamt / bw->rate;
48     // bwstart变量复用, 这个时候, bwstart含义为, 本次统计周期理论开销的时间
49     bw->bwstart.tv_sec = waitlen / 1000000L;
50     bw->bwstart.tv_usec = waitlen % 1000000L;
51 
52     // 如果理论开销时间 >  实际开销时间, 则需要做限速
53     if (timercmp(&bw->bwstart, &bw->bwend, >)) {
54         // bwend变量复用, 这个时间, bwend含义为, 理论开销时间 和 实际开销时间的差值, 既需要sleep的时间, 确保达到限速到指定的rate值
55         timersub(&bw->bwstart, &bw->bwend, &bw->bwend);
56 
57         // 如果差值达到了秒级, 则需要降低统计周期阈值, 确保统计相对精确
58         // thresh变为原先的1/2, 但不能低于buflen的1/4
59         if (bw->bwend.tv_sec) {
60             bw->thresh /= 2;
61             if (bw->thresh < bw->buflen / 4)
62                 bw->thresh = bw->buflen / 4;
63         } 
64         // 如果差值小于10毫秒, 则需要加大统计周期阈值, 确保统计相对精确
65         // thresh变为原先的2倍, 但不能高于buflen的8倍
66         else if (bw->bwend.tv_usec < 10000) {
67             bw->thresh *= 2;
68             if (bw->thresh > bw->buflen * 8)
69                 bw->thresh = bw->buflen * 8;
70         }
71 
72         // 乖乖的睡一会吧, 以达到限速目的
73         TIMEVAL_TO_TIMESPEC(&bw->bwend, &ts);
74         while (nanosleep(&ts, &rm) == -1) {
75             if (errno != EINTR)
76                 break;
77             ts = rm;
78         }
79     }
80 
81     // 新的统计周期开始, 初始化lamt, bwstart变量
82     bw->lamt = 0;
83     gettimeofday(&bw->bwstart, NULL);
84 }

posted on 2014-09-22 17:45 stone2083 阅读(2455) 评论(4)  编辑  收藏 所属分类: c

Feedback

# re: SCP限速逻辑实现--带中文注释的bandwidth_limit函数 2014-09-23 15:53 提升机

学习了,多谢分享  回复  更多评论   

# re: SCP限速逻辑实现--带中文注释的bandwidth_limit函数 2014-09-23 20:40 名皮网

收藏了。多谢分享  回复  更多评论   

# re: SCP限速逻辑实现--带中文注释的bandwidth_limit函数 2014-09-30 09:36 sjxifen

怎样用的呢?  回复  更多评论   


只有注册用户登录后才能发表评论。


网站导航: