<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    小碼哥

    誰謂河廣,一葦杭之

       :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
      7 隨筆 :: 17 文章 :: 74 評論 :: 0 Trackbacks

    常用鏈接

    留言簿(21)

    隨筆分類

    隨筆檔案

    文章分類

    文章檔案

    相冊

    訂閱Canvas

    搜索

    最新評論

    閱讀排行榜

    評論排行榜

    好久沒有在這里寫點東西了,要養成書寫記錄的習慣。

    這里簡單的討論一下java設計網絡程序中如何控制上傳和下載速度,我們常見的FTP,HTTP,BT等協議都是TCP的,但是現在流行的utorrent卻基于UDP實現了自己UTP協議(UDP+擁塞控制),不管使用什么協議,站在I/O的角度來說,限速的控制思路都是一樣的。

    思路很簡單,如下:

    1.假設下載或者上傳速度上限是m (KB/s),那么發送一個固定的字節數據(假設是n字節)的時間花費是:n/m;
    2.假設現在要發送n字節的數據,那么理論所需的時間應該是n/m,而在實際情況下,發送n字節的數據只花費了t秒,那么發送該發送線程就應該睡眠n/m-t秒,這樣就基本實現了速度的控制。

    代碼以TCP為例
    速度控制
     1 package com.actiontec.net.bandwidth;
     2 
     3 /**
     4  * 
     5  * @author Le
     6  * 
     7  */
     8 public class BandwidthLimiter {
     9 
    10     /* KB */
    11     private static Long KB = 1024l;
    12 
    13     /* The smallest count chunk length in bytes */
    14     private static Long CHUNK_LENGTH = 1024l;
    15 
    16     /* How many bytes will be sent or receive */
    17     private int bytesWillBeSentOrReceive = 0;
    18 
    19     /* When the last piece was sent or receive */
    20     private long lastPieceSentOrReceiveTick = System.nanoTime();
    21 
    22     /* Default rate is 1024KB/s */
    23     private int maxRate = 1024;
    24 
    25     /* Time cost for sending CHUNK_LENGTH bytes in nanoseconds */
    26     private long timeCostPerChunk = (1000000000l * CHUNK_LENGTH)
    27             / (this.maxRate * KB);
    28 
    29     /**
    30      * Initialize a BandwidthLimiter object with a certain rate.
    31      * 
    32      * @param maxRate
    33      *            the download or upload speed in KBytes
    34      */
    35     public BandwidthLimiter(int maxRate) {
    36         this.setMaxRate(maxRate);
    37     }
    38 
    39     /**
    40      * Set the max upload or download rate in KB/s. maxRate must be grater than
    41      * 0. If maxRate is zero, it means there is no bandwidth limit.
    42      * 
    43      * @param maxRate
    44      *            If maxRate is zero, it means there is no bandwidth limit.
    45      * @throws IllegalArgumentException
    46      */
    47     public synchronized void setMaxRate(int maxRate)
    48             throws IllegalArgumentException {
    49         if (maxRate < 0) {
    50             throw new IllegalArgumentException("maxRate can not less than 0");
    51         }
    52         this.maxRate = maxRate < 0 ? 0 : maxRate;
    53         if (maxRate == 0)
    54             this.timeCostPerChunk = 0;
    55         else
    56             this.timeCostPerChunk = (1000000000l * CHUNK_LENGTH)
    57                     / (this.maxRate * KB);
    58     }
    59 
    60     /**
    61      * Next 1 byte should do bandwidth limit.
    62      */
    63     public synchronized void limitNextBytes() {
    64         this.limitNextBytes(1);
    65     }
    66 
    67     /**
    68      * Next len bytes should do bandwidth limit
    69      * 
    70      * @param len
    71      */
    72     public synchronized void limitNextBytes(int len) {
    73         this.bytesWillBeSentOrReceive += len;
    74 
    75         /* We have sent CHUNK_LENGTH bytes */
    76         while (this.bytesWillBeSentOrReceive > CHUNK_LENGTH) {
    77             long nowTick = System.nanoTime();
    78             long missedTime = this.timeCostPerChunk
    79                     - (nowTick - this.lastPieceSentOrReceiveTick);
    80             if (missedTime > 0) {
    81                 try {
    82                     Thread.sleep(missedTime / 1000000,
    83                             (int) (missedTime % 1000000));
    84                 } catch (InterruptedException e) {
    85                     e.printStackTrace();
    86                 }
    87             }
    88             this.bytesWillBeSentOrReceive -= CHUNK_LENGTH;
    89             this.lastPieceSentOrReceiveTick = nowTick
    90                     + (missedTime > 0 ? missedTime : 0);
    91         }
    92     }
    93 }
    94 

    下載控制
     1 package com.actiontec.net.bandwidth;
     2 
     3 import java.io.IOException;
     4 import java.io.InputStream;
     5 
     6 /**
     7  * @author Le
     8  *
     9  */
    10 public class DownloadLimiter extends InputStream {
    11     private InputStream is = null;
    12     private BandwidthLimiter bandwidthLimiter = null;
    13     
    14     public DownloadLimiter(InputStream is, BandwidthLimiter bandwidthLimiter)
    15     {
    16         this.is = is;
    17         this.bandwidthLimiter = bandwidthLimiter;
    18     }
    19     @Override
    20     public int read() throws IOException {
    21         if(this.bandwidthLimiter != null)
    22             this.bandwidthLimiter.limitNextBytes();
    23         return this.is.read();
    24     }
    25 
    26     public int read(byte b[], int off, int len) throws IOException
    27     {
    28         if (bandwidthLimiter != null)
    29             bandwidthLimiter.limitNextBytes(len);
    30         return this.is.read(b, off, len);
    31     }
    32 }

    同樣,上傳控制

     1 package com.actiontec.net.bandwidth;
     2 
     3 import java.io.IOException;
     4 import java.io.OutputStream;
     5 
     6 /**
     7  * @author Le
     8  *
     9  */
    10 public class UploadLimiter extends OutputStream {
    11     private OutputStream os = null;
    12     private BandwidthLimiter bandwidthLimiter = null;
    13     
    14     public UploadLimiter(OutputStream os, BandwidthLimiter bandwidthLimiter)
    15     {
    16         this.os = os;
    17         this.bandwidthLimiter = bandwidthLimiter;
    18     }
    19     
    20     @Override
    21     public void write(int b) throws IOException {
    22         if (bandwidthLimiter != null)
    23             bandwidthLimiter.limitNextBytes();
    24         this.os.write(b);
    25     }
    26     
    27     public void write(byte[] b, int off, int len) throws IOException {
    28         if (bandwidthLimiter != null)
    29             bandwidthLimiter.limitNextBytes(len);
    30         this.os.write(b, off, len);
    31     }
    32 
    33 }

    對于一個TCP socket

    1 ServerSocket socket = new ServerSocket();
    2 //其它初始化略

     1 //從socket中以一定的速率讀數據
     2 //```java
     3 DownloadLimiter dl = new DownloadLimiter(socket.getInputStream(), new BandwidthLimiter(6250));
     4 is = new DataInputStream(dl);
     5 
     6 //讀數據
     7 int len = is.readInt();
     8 ByteBuffer buffer = ByteBuffer.allocate(4 + len);
     9 buffer.putInt(len);
    10 is.readFully(buffer.array(), 4, buffer.remaining());
    11 //```
    12 
    13 //以一定的速率寫數據到socket
    14 //```java
    15 UploadLimiter ul = new UploadLimiter(socket.getOutputStream(), new BandwidthLimiter(6250));
    16 ul.write();
    17 //```

    在多線程環境下也可以使用上述的方法。最后附圖是任務管理器的網絡利用率圖6250KB/s(也就是50000kb/s,附圖中網絡利用率也在5%左右,所以應該這個做法還算準確)
    posted on 2012-10-18 16:34 小碼哥 閱讀(12960) 評論(2)  編輯  收藏 所屬分類: Java語言學習

    評論

    # re: Java程序如何限速(控制下載和上傳速度) 2012-11-09 10:52 chwj
    我調整new BandwidthLimiter(6250)為其他數值后(除0外),測試下載均顯示利用率為0.35左右(100Mbps),而服務器端則顯示發送在2.0~1.8MBps浮動。  回復  更多評論
      

    # re: Java程序如何限速(控制下載和上傳速度) 2012-11-10 00:03 小碼哥
    @chwj
    我在使用過程中也發現不準,根據每次發送數據大?。ù笮』疽恢卤容^好)適當調整CHUNK_LENGTH大小,可能會有些效果。單線程情況下會準一些。暫時還沒有想到其它好的方法。  回復  更多評論
      

    主站蜘蛛池模板: 国产成人亚洲精品狼色在线| 亚洲综合一区二区精品久久| 最近免费mv在线观看动漫| 精品国产_亚洲人成在线| 久久久青草青青国产亚洲免观 | 又长又大又粗又硬3p免费视频| 成人最新午夜免费视频| 亚洲熟女www一区二区三区| 亚洲国产综合人成综合网站| 美女视频黄频a免费大全视频| 五月婷婷亚洲综合| 国产黄片不卡免费| 亚洲综合婷婷久久| 青娱乐免费视频在线观看| 国产免费A∨在线播放| 亚洲国产精品免费视频| 国产成人精品免费直播| 中文免费观看视频网站| www成人免费视频| 亚洲欧美日韩久久精品| 高清在线亚洲精品国产二区| 最近高清中文字幕免费| 午夜肉伦伦影院久久精品免费看国产一区二区三区 | va亚洲va日韩不卡在线观看| 最近免费中文字幕大全免费| 一级毛片免费播放视频| 亚洲日韩AV一区二区三区中文| 久久伊人久久亚洲综合| 99久久99久久精品免费观看| 成人精品综合免费视频| 亚洲熟女综合一区二区三区| 亚洲成人精品久久| 激情97综合亚洲色婷婷五| 国产麻豆剧传媒精品国产免费| sss在线观看免费高清| 亚洲欧好州第一的日产suv| 精品日韩亚洲AV无码一区二区三区| 亚洲精品tv久久久久久久久久| 日本视频免费在线| 波多野结衣免费在线| 久久免费的精品国产V∧|