-2

まず第一に、UDP が信頼できるプロトコルではないことは知っていますが、UDP でこれを行う必要があり、最終的に発生する可能性のある結果を認識しています。

byte32 バイトのチャンクに分割した長い配列があるとしList<byte[]>ます。これは、送信される各パケットの長さが 32 バイトになることを意味します。

これらのパケットはforeachループで送信され、宛先に到着するかどうかは気にしません。つまり、ホストからの確認を期待していません (少なくとも今のところ)。

そして私の質問は、サーバーがパケットを受信して​​いるときに、サーバーの現在の転送速度 (できれば kbps) を計算するにはどうすればよいですか?

どうすればそのような計算を達成できるかについて少し混乱しています...

4

2 に答える 2

5

質問が「転送速度を計算する方法」である場合は、ダウンロードされたバイトの合計数を経過した合計秒数で割ることができます。

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

C# で時間を測定する良い方法はStopWatchクラスです。コンピューター サイエンスの K は 1024 (または 2^10) であるため、バイト数を 1024 で割って (またはシフトして)、秒数で割ることができます。そのキロバイト数をダウンロードするのにかかりました。


平均転送速度に関心がある場合は、ダウンロードされたバイト数を間隔で測定する必要があります。これは、測定点とダウンロードされたバイト数とそれにかかった時間を保持する 2 次元のリストで行うことができます。簡単にするために、計算を行うクラスに分割します

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 で割ります。

于 2012-04-08T00:28:20.470 に答える
1

fireBwall では、確認するたびに転送速度を更新するシンプルなシステムを使用しています。また、送信された情報の合計も保存されます。fireBwall の Google Code ページからこれをコピーしました。

/// <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";
        }
    }
}

転送速度を扱う非同期環境では、かなりうまく機能します。

于 2012-04-08T02:14:32.913 に答える