stone2083

          SCP限速邏輯實(shí)現(xiàn)--帶中文注釋的bandwidth_limit函數(shù)

          SCP限速邏輯實(shí)現(xiàn)--帶中文注釋的bandwidth_limit函數(shù)

          SCP支持限速, 通過(guò)-l參數(shù), 指定拷貝的速度
           -l limit
                       Limits the used bandwidth, specified in Kbit/s.

          具體實(shí)現(xiàn), 是在misc.c中的bandwidth_limit函數(shù)
          下面附上帶中文注釋的bandwidth_limit函數(shù)代碼
           1 struct bwlimit {
           2     size_t buflen;                 // 每次read的buf長(zhǎng)度
           3     u_int64_t rate, thresh, lamt;  // rate:  限速速率, 單位kpbs
           4                                    // thresh:統(tǒng)計(jì)周期,read長(zhǎng)度到了指定閾值, 觸發(fā)限速統(tǒng)計(jì)
           5                                    // lamt:  一次統(tǒng)計(jì)周期內(nèi), read了多少長(zhǎng)度
           6     struct timeval bwstart, bwend; // bwstart: 統(tǒng)計(jì)周期之開(kāi)始時(shí)間
           7                                    // bwend:   統(tǒng)計(jì)周期之結(jié)束時(shí)間
           8 };
           9 
          10 void bandwidth_limit_init(struct bwlimit *bw, u_int64_t kbps, size_t buflen)
          11 {
          12     bw->buflen = buflen;          // 初始化read buf長(zhǎng)度
          13     bw->rate = kbps;              // 初始化限速速率
          14     bw->thresh = bw->rate;        // 初始化統(tǒng)計(jì)周期
          15     bw->lamt = 0;                 // 初始化當(dāng)前read長(zhǎng)度
          16     timerclear(&bw->bwstart);     // 初始化統(tǒng)計(jì)開(kāi)始時(shí)間
          17     timerclear(&bw->bwend);       // 初始化統(tǒng)計(jì)結(jié)束時(shí)間
          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     // 設(shè)置統(tǒng)計(jì)開(kāi)始時(shí)間, 為當(dāng)前時(shí)間
          26     if (!timerisset(&bw->bwstart)) {
          27         gettimeofday(&bw->bwstart, NULL);
          28         return;
          29     }
          30 
          31     // 設(shè)置當(dāng)前read長(zhǎng)度
          32     bw->lamt += read_len;
          33     // 判斷當(dāng)前read長(zhǎng)度是否到達(dá)統(tǒng)計(jì)周期的閾值
          34     if (bw->lamt < bw->thresh)
          35         return;
          36 
          37     // 設(shè)置統(tǒng)計(jì)結(jié)束時(shí)間,為當(dāng)前時(shí)間
          38     gettimeofday(&bw->bwend, NULL);
          39     // bwend變量復(fù)用, 這個(gè)時(shí)候, bwend含義為, 本次統(tǒng)計(jì)周期實(shí)際開(kāi)銷(xiāo)的時(shí)間: 既read thresh長(zhǎng)度字節(jié),花了多少時(shí)間.
          40     timersub(&bw->bwend, &bw->bwstart, &bw->bwend);
          41     if (!timerisset(&bw->bwend))
          42         return;
          43 
          44     // 將單位從Byte變成bit
          45     bw->lamt *= 8;
          46     // 根據(jù)限速速率, 計(jì)算理論應(yīng)該花費(fèi)多少時(shí)間
          47     waitlen = (double)1000000L * bw->lamt / bw->rate;
          48     // bwstart變量復(fù)用, 這個(gè)時(shí)候, bwstart含義為, 本次統(tǒng)計(jì)周期理論開(kāi)銷(xiāo)的時(shí)間
          49     bw->bwstart.tv_sec = waitlen / 1000000L;
          50     bw->bwstart.tv_usec = waitlen % 1000000L;
          51 
          52     // 如果理論開(kāi)銷(xiāo)時(shí)間 >  實(shí)際開(kāi)銷(xiāo)時(shí)間, 則需要做限速
          53     if (timercmp(&bw->bwstart, &bw->bwend, >)) {
          54         // bwend變量復(fù)用, 這個(gè)時(shí)間, bwend含義為, 理論開(kāi)銷(xiāo)時(shí)間 和 實(shí)際開(kāi)銷(xiāo)時(shí)間的差值, 既需要sleep的時(shí)間, 確保達(dá)到限速到指定的rate值
          55         timersub(&bw->bwstart, &bw->bwend, &bw->bwend);
          56 
          57         // 如果差值達(dá)到了秒級(jí), 則需要降低統(tǒng)計(jì)周期閾值, 確保統(tǒng)計(jì)相對(duì)精確
          58         // thresh變?yōu)樵鹊?/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毫秒, 則需要加大統(tǒng)計(jì)周期閾值, 確保統(tǒng)計(jì)相對(duì)精確
          65         // thresh變?yōu)樵鹊?倍, 但不能高于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         // 乖乖的睡一會(huì)吧, 以達(dá)到限速目的
          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     // 新的統(tǒng)計(jì)周期開(kāi)始, 初始化lamt, bwstart變量
          82     bw->lamt = 0;
          83     gettimeofday(&bw->bwstart, NULL);
          84 }

          posted on 2014-09-22 17:45 stone2083 閱讀(2489) 評(píng)論(4)  編輯  收藏 所屬分類(lèi): c

          Feedback

          # re: SCP限速邏輯實(shí)現(xiàn)--帶中文注釋的bandwidth_limit函數(shù) 2014-09-23 15:53 提升機(jī)

          學(xué)習(xí)了,多謝分享  回復(fù)  更多評(píng)論   

          # re: SCP限速邏輯實(shí)現(xiàn)--帶中文注釋的bandwidth_limit函數(shù) 2014-09-23 20:40 名皮網(wǎng)

          收藏了。多謝分享  回復(fù)  更多評(píng)論   

          # re: SCP限速邏輯實(shí)現(xiàn)--帶中文注釋的bandwidth_limit函數(shù) 2014-09-30 09:36 sjxifen

          怎樣用的呢?  回復(fù)  更多評(píng)論   


          只有注冊(cè)用戶(hù)登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 商南县| 罗江县| 原平市| 句容市| 河西区| 吴旗县| 晋城| 当涂县| 平果县| 万源市| 会宁县| 祁门县| 湖州市| 渑池县| 莆田市| 徐州市| 邢台县| 陵川县| 志丹县| 屏山县| 阳新县| 隆昌县| 清远市| 尉氏县| 海阳市| 广平县| 汝阳县| 靖边县| 郑州市| 黔南| 邓州市| 额尔古纳市| 吉林市| 文山县| 南开区| 苏州市| 大田县| 汤阴县| 湘潭市| 瓮安县| 电白县|