2012-04-07 5 views
-2

Прежде всего, я знаю, что UDP не является надежным протоколом, но мне нужно это в UDP, и я знаю о последствиях, которые могут произойти в конечном итоге.Как рассчитать скорость передачи UDP (kbps) в C#?

Предположим, у меня есть длинный массив byte, который я разделил в кусках 32 байта на List<byte[]>. Это означает, что каждый отправленный пакет будет иметь длину 32 байта.

Эти пакеты будут отправлены в цикле foreach, и мне все равно, если они прибудут в пункт назначения или нет. Значение Я не ожидаю подтверждения от хоста (по крайней мере пока).

И мой вопрос заключается в том, как я могу рассчитать текущую скорость передачи (предпочтительно в kbps) сервера, пока он принимает пакеты?

Я немного запутался о том, как я мог бы достичь такого расчета ...

+2

kbps = kilobytes/second, поэтому 'StopWatch' и счетчик загруженных байтов,' (bytes/1024)/watch.Elapsed.TotalSeconds' ... – Patrick

+1

Действительно. В этой статье есть * много лишней информации. –

+0

@caesay Мне тоже нет, но что вы собираетесь делать ...:/ –

ответ

3

Если ваш вопрос «как рассчитать скорость передачи данных», вы можете разделить общее количество загруженных байт в общей сложности количество прошедших секунд.

bytes 
--------- = transfer rate 
    seconds 

Хороший способ измерения времени в C# является StopWatch класс, а с K в компьютерной науке является 1024 (или 2^10), вы можете разделить число байтов с 1024 (или переместить его), а затем разделите его на количество секунд, необходимое для загрузки этого количества килобайт.


Если вас интересует средняя скорость передачи данных, вам необходимо измерить загруженные байты в интервалы. Вы можете сделать это с двухмерным списком, удерживая точки измерения и загруженные байты и время, которое потребовалось. Для простоты, разбить его из класса в том, что делает расчеты

private readonly Stopwatch watch; 
private readonly long[,] average; 

public .ctor() { 
    // use 10 measure points, for a larger or smaller average, adjust the 10 
    average = new long[10, 2]; 
    watch = Stopwatch.StartNew(); 
} 

public long BytesTransferred { 
    set { 
     for (int i = average.GetLength(0) - 1; i > 0; --i) { 
      average[i, 0] = average[i - 1, 0]; 
      average[i, 1] = average[i - 1, 1]; 
     } 
     average[0, 0] = sent = value; 
     average[0, 1] = watch.ElapsedMilliseconds; 
    } 
} 

public long TransferRate { 
    get { 
     int l = average.GetLength(0) - 1; 
     double bytes = average[0, 0] - average[l, 0]; 
     double seconds = (average[0, 1] - average[l, 1])/1000d; 
     return (long)(bytes/seconds); 
    } 
} 

В вашем методе загрузки, перерыв нового потока, создать экземпляр указанного класса, и вызвать BytesTransferred = totalBytes; в каждом интервале. TransferRate будет рассчитываться каждый раз, когда вы вызываете TransferRate. Обратите внимание, что это байты/, если вы хотите другой блок, разделите его на 1024 соответственно.

+0

Почему downvote. Предоставлял ли я ложную информацию? – Patrick

+0

Просто, чтобы быть ясным, это был не я. Это похоже на простой ответ, который я ищу ... :) В принципе, таймер должен быть запущен, когда начинается передача, и мне просто нужно разделить все загруженные байты с истекшим временем от секундомера, верно? Это кажется достаточно простым, но у меня один вопрос.Разве это не будет средняя скорость передачи, а не постоянная скорость передачи в определенный момент времени? Или, может быть, это идиотский вопрос, и я не понимаю какой-то базовой концепции !? –

+0

@ RicardoAmaral Да, это будет общее среднее. Если вы хотите, чтобы скорость передачи была меньше времени, вы можете вызвать «Stop()» в StopWatch (что в основном приостанавливает ее), когда вы скачали что-то и хотите что-то проверить, а затем вызовите 'Start()', когда вы начните загрузку снова. – Patrick

1

Мы используем простую систему на fireBwall, которая обновляет скорость передачи каждый раз, когда вы ее проверяете. Он также сохраняет всю отправленную информацию. Я просто скопировал это с страницы Google Code для fireBwall.

/// <summary> 
/// Class to manage an adapters total transfered data 
/// </summary> 
public class BandwidthCounter 
{ 
    /// <summary> 
    /// Class to manage an adapters current transfer rate 
    /// </summary> 
    class MiniCounter 
    { 
     public uint bytes = 0; 
     public uint kbytes = 0; 
     public uint mbytes = 0; 
     public uint gbytes = 0; 
     public uint tbytes = 0; 
     public uint pbytes = 0; 
     DateTime lastRead = DateTime.Now; 

     /// <summary> 
     /// Adds bits(total misnomer because bits per second looks a lot better than bytes per second) 
     /// </summary> 
     /// <param name="count">The number of bits to add</param> 
     public void AddBytes(uint count) 
     { 
      bytes += count; 
      while (bytes > 1024) 
      { 
       kbytes++; 
       bytes -= 1024; 
      } 
      while (kbytes > 1024) 
      { 
       mbytes++; 
       kbytes -= 1024; 
      } 
      while (mbytes > 1024) 
      { 
       gbytes++; 
       mbytes -= 1024; 
      } 
      while (gbytes > 1024) 
      { 
       tbytes++; 
       gbytes -= 1024; 
      } 
      while (tbytes > 1024) 
      { 
       pbytes++; 
       tbytes -= 1024; 
      } 
     } 

     /// <summary> 
     /// Returns the bits per second since the last time this function was called 
     /// </summary> 
     /// <returns></returns> 
     public override string ToString() 
     { 
      if (pbytes > 0) 
      { 
       double ret = (double)pbytes + ((double)((double)tbytes/1024)); 
       ret = ret/(DateTime.Now - lastRead).TotalSeconds; 
       lastRead = DateTime.Now; 
       string s = ret.ToString(); 
       if (s.Length > 6) 
        s = s.Substring(0, 6); 
       return s + " Pb"; 
      } 
      else if (tbytes > 0) 
      { 
       double ret = (double)tbytes + ((double)((double)gbytes/1024)); 
       ret = ret/(DateTime.Now - lastRead).TotalSeconds; 
       lastRead = DateTime.Now; 
       string s = ret.ToString(); 
       if (s.Length > 6) 
        s = s.Substring(0, 6); 
       return s + " Tb"; 
      } 
      else if (gbytes > 0) 
      { 
       double ret = (double)gbytes + ((double)((double)mbytes/1024)); 
       ret = ret/(DateTime.Now - lastRead).TotalSeconds; 
       lastRead = DateTime.Now; 
       string s = ret.ToString(); 
       if (s.Length > 6) 
        s = s.Substring(0, 6); 
       return s + " Gb"; 
      } 
      else if (mbytes > 0) 
      { 
       double ret = (double)mbytes + ((double)((double)kbytes/1024)); 
       ret = ret/(DateTime.Now - lastRead).TotalSeconds; 
       lastRead = DateTime.Now; 
       string s = ret.ToString(); 
       if (s.Length > 6) 
        s = s.Substring(0, 6); 
       return s + " Mb"; 
      } 
      else if (kbytes > 0) 
      { 
       double ret = (double)kbytes + ((double)((double)bytes/1024)); 
       ret = ret/(DateTime.Now - lastRead).TotalSeconds; 
       lastRead = DateTime.Now; 
       string s = ret.ToString(); 
       if (s.Length > 6) 
        s = s.Substring(0, 6); 
       return s + " Kb"; 
      } 
      else 
      { 
       double ret = bytes; 
       ret = ret/(DateTime.Now - lastRead).TotalSeconds; 
       lastRead = DateTime.Now; 
       string s = ret.ToString(); 
       if (s.Length > 6) 
        s = s.Substring(0, 6); 
       return s + " b"; 
      } 
     } 
    } 

    private uint bytes = 0; 
    private uint kbytes = 0; 
    private uint mbytes = 0; 
    private uint gbytes = 0; 
    private uint tbytes = 0; 
    private uint pbytes = 0; 
    MiniCounter perSecond = new MiniCounter(); 

    /// <summary> 
    /// Empty constructor, because thats constructive 
    /// </summary> 
    public BandwidthCounter() 
    { 

    } 

    /// <summary> 
    /// Accesses the current transfer rate, returning the text 
    /// </summary> 
    /// <returns></returns> 
    public string GetPerSecond() 
    { 
     string s = perSecond.ToString() + "/s"; 
     perSecond = new MiniCounter(); 
     return s; 
    } 

    /// <summary> 
    /// Adds bytes to the total transfered 
    /// </summary> 
    /// <param name="count">Byte count</param> 
    public void AddBytes(uint count) 
    { 
     // overflow max 
     if ((count * 8) >= Int32.MaxValue) 
      return; 

     count = 8 * count; 
     perSecond.AddBytes(count); 
     bytes += count; 
     while (bytes > 1024) 
     { 
      kbytes++; 
      bytes -= 1024; 
     } 
     while (kbytes > 1024) 
     { 
      mbytes++; 
      kbytes -= 1024; 
     } 
     while (mbytes > 1024) 
     { 
      gbytes++; 
      mbytes -= 1024; 
     } 
     while (gbytes > 1024) 
     { 
      tbytes++; 
      gbytes -= 1024; 
     } 
     while (tbytes > 1024) 
     { 
      pbytes++; 
      tbytes -= 1024; 
     } 
    } 

    /// <summary> 
    /// Prints out a relevant string for the bits transfered 
    /// </summary> 
    /// <returns></returns> 
    public override string ToString() 
    { 
     if (pbytes > 0) 
     { 
      double ret = (double)pbytes + ((double)((double)tbytes/1024)); 
      string s = ret.ToString(); 
      if (s.Length > 6) 
       s = s.Substring(0, 6); 
      return s + " Pb"; 
     } 
     else if (tbytes > 0) 
     { 
      double ret = (double)tbytes + ((double)((double)gbytes/1024)); 
      string s = ret.ToString(); 
      if (s.Length > 6) 
       s = s.Substring(0, 6); 
      return s + " Tb"; 
     } 
     else if (gbytes > 0) 
     { 
      double ret = (double)gbytes + ((double)((double)mbytes/1024)); 
      string s = ret.ToString(); 
      if (s.Length > 6) 
       s = s.Substring(0, 6); 
      return s + " Gb"; 
     } 
     else if (mbytes > 0) 
     { 
      double ret = (double)mbytes + ((double)((double)kbytes/1024)); 
      string s = ret.ToString(); 
      if (s.Length > 6) 
       s = s.Substring(0, 6); 
      return s + " Mb"; 
     } 
     else if (kbytes > 0) 
     { 
      double ret = (double)kbytes + ((double)((double)bytes/1024)); 
      string s = ret.ToString(); 
      if (s.Length > 6) 
       s = s.Substring(0, 6); 
      return s + " Kb"; 
     } 
     else 
     { 
      string s = bytes.ToString(); 
      if (s.Length > 6) 
       s = s.Substring(0, 6); 
      return s + " b"; 
     } 
    } 
} 

Хорошо работает для нас в асинхронной среде, связанной со скоростями передачи.

+1

Я бы рекомендовал использовать StopWatch вместо 'DateTime.Now' или, по крайней мере,' DateTime.UtcNow', которые не имеют накладных расходов по часовому поясу, так как вас интересует только время, а не местное время. – Patrick

+0

Кроме того, ваш код немного избыточен. 'while (bytes> 1024) {kbytes ++; bytes - = 1024; } 'можно заменить на' kbytes = bytes/1024; bytes% = 1024; 'приводит к двум операциям вместо времени и побитовому сокращению для * каждого * единиц. – Patrick

+0

В вашем методе 'AddBytes', почему вы умножаете число с 8, мне кажется, что вы предоставляете ложную информацию, говоря, что ваша скорость передачи на самом деле в восемь раз выше, чем на самом деле? – Patrick

Смежные вопросы