在不到一秒的时间内计算发送文件速度/秒(不使用 thread.sleep)

发布于 2024-12-29 02:12:24 字数 725 浏览 1 评论 0原文

这是文件传输(服务器-客户端tcp套接字)

下面的代码显示了每秒的传输速率(kb/s)。

我想在每次向客户端发送数据时显示速度(rate/s)。如何每次计算速度(不使用thread.sleep(1000))?

private void timeElasped()
    {
        int rate = 0;
        int prevSent = 0;
        while (fileTransfer.busy)
        {
            rate = fileTransfer.Sent - prevSent ;
            prevSum = fileTransfer.Sent;
            RateLabel(string.Format("{0}/Sec", CnvrtUnit(rate)));
            if(rate!=0)
                Timeleft = (fileTransfer.fileSize - fileTransfer.sum) / rate;
            TimeSpan t = TimeSpan.FromSeconds(Timeleft);
            timeLeftLabel(FormatRemainingText(rate, t));
            Thread.Sleep(1000);
        }
    }

This is a file transfer (Server-Client tcp sockets)

The code below shows the transfer rate per second (kb/s) every one second.

I want to show the the speed (rate/s) every time I send the data to the client. How do I calculate the speed every time (without usings thread.sleep(1000))?

private void timeElasped()
    {
        int rate = 0;
        int prevSent = 0;
        while (fileTransfer.busy)
        {
            rate = fileTransfer.Sent - prevSent ;
            prevSum = fileTransfer.Sent;
            RateLabel(string.Format("{0}/Sec", CnvrtUnit(rate)));
            if(rate!=0)
                Timeleft = (fileTransfer.fileSize - fileTransfer.sum) / rate;
            TimeSpan t = TimeSpan.FromSeconds(Timeleft);
            timeLeftLabel(FormatRemainingText(rate, t));
            Thread.Sleep(1000);
        }
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

拧巴小姐 2025-01-05 02:12:24

您需要做出两个决定:

  1. 您希望在多长时间内保持平均传输速度?
  2. 您想多久更新/报告一次结果?

回想一下,不存在当前瞬时传输速度这样的东西。或者,更准确地说,当前瞬时传输速度始终是网络接口的完整物理速度(例如 100 Mbps)或零,对应于“这一微秒内有一个数据包正在发送/接收”和“线路闲着”。所以你必须平均。

在上面的代码中,您选择了一秒作为 (1) 和 (2) 的值。 (1) 和 (2) 相等是最简单的编码情况。

我建议您为 (1) 选择更长的期限。平均仅超过一秒将导致除了最流畅的文件传输之外的所有传输速度都相当不稳定。例如,Cisco IOS 默认情况下平均时间超过 5 分钟,并且不允许您配置少于 30 秒。

对于(2),您可以继续使用 1 秒,或者,如果您愿意,甚至可以使用不到 1 秒。

为 (1) 选择一个值,该值是为 (2) 选择的值的倍数。令n 为(1) 除以(2)。例如,(1) 为 10 秒,(2) 为 500 毫秒,n=20

创建一个包含 n 条目的环形缓冲区。每次 (2) 过去后,将环形缓冲区中最旧的条目替换为自上一次 (2) 过去以来传输的字节数,然后重新计算传输速度,即缓冲区中所有条目的总和除以 (1) 。

You have two decisions to make:

  1. Over how much time do you want to take the average transfer speed?
  2. How often do you want to update/report the result?

Recall that there is no such thing as the current instantaneous transfer speed. Or, more correctly, the current instantaneous transfer speed is always either the full physical speed of your network interface (e.g. 100 Mbps) or zero, corresponding to the situations "there is a packet being sent/received right this microsecond" and "the line is idle". So you have to average.

In the code above, you have chosen one second as the value for both (1) and (2). (1) and (2) being equal is the simplest case to code.

I recommend that you choose a longer period for (1). Averaging over only one second is going to make for a pretty jittery transfer speed on all but the smoothest file transfers. Consider, for example, that Cisco IOS averages over 5 minutes by default and doesn't let you configure less than 30 seconds.

For (2), you can continue to use 1 second, or, if you like, even less than one second.

Choose a value for (1) that is a multiple of the value you choose for (2). Let n be (1) divides by (2). For example, (1) is 10 seconds, (2) is 500ms, and n=20.

Create a ring buffer with n entries. Every time (2) elapses, replace the oldest entry in the ring buffer with the number of bytes transferred since the previous time (2) elapsed, then recalculate the transfer speed as the sum of all the entries in the buffer divided by (1).

乜一 2025-01-05 02:12:24

在表单构造函数中

Timer timer1 = new Time();
public Form1()
{
    InitializeComponent();
    this.timer1.Enabled = true;
    this.timer1.Interval = 1000;
    this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
}

或从工具箱添加它并设置先前的值

发送的字节总和应该是公共的,以便我们的方法可以每秒获取其值

long sentBytes = 0;      //the sent bytes that updated from sending method
long prevSentBytes = 0;   //which references to the previous sentByte
double totalSeconds = 0;   //seconds counter to show total time .. it increases everytime the timer1 ticks.
private void timer1_Tick(object sender, EventArgs e)
{
    long speed = sentBytes - prevSentBytes ;  //here's the Transfer-Rate or Speed
    prevSentBytes = sentBytes ;
    labelSpeed.Text = CnvrtUnit(speed) + "/S";   //display the speed like (100 kb/s) to a label
    if (speed > 0)                //considering that the speed would be 0 sometimes.. we avoid dividing on 0 exception
    {
        totalSeconds++;     //increasing total-time
        labelTime.Text = TimeToText(TimeSpan.FromSeconds((sizeAll - sumAll) / speed));
        //displaying time-left in label
        labelTotalTime.Text = TimeToText(TimeSpan.FromSeconds(totalSeconds));
        //displaying total-time in label
    }
}

private string TimeToText(TimeSpan t)
{
    return string.Format("{2:D2}:{1:D2}:{0:D2}", t.Seconds, t.Minutes, t.Hours);
}

private string CnvrtUnit(long source)
{
    const int byteConversion = 1024;
    double bytes = Convert.ToDouble(source);

    if (bytes >= Math.Pow(byteConversion, 3)) //GB Range
    {
        return string.Concat(Math.Round(bytes / Math.Pow(byteConversion, 3), 2), " GB");
    }
    else if (bytes >= Math.Pow(byteConversion, 2)) //MB Range
    {
        return string.Concat(Math.Round(bytes / Math.Pow(byteConversion, 2), 2), " MB");
    }
    else if (bytes >= byteConversion) //KB Range
    {
        return string.Concat(Math.Round(bytes / byteConversion, 2), " KB");
    }
    else //Bytes
    {
        return string.Concat(bytes, " Bytes");
    }
}

in form constructor

Timer timer1 = new Time();
public Form1()
{
    InitializeComponent();
    this.timer1.Enabled = true;
    this.timer1.Interval = 1000;
    this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
}

or add it from toolbox and set the previous values

the sum of sent bytes should be public so our method can get its value every second

long sentBytes = 0;      //the sent bytes that updated from sending method
long prevSentBytes = 0;   //which references to the previous sentByte
double totalSeconds = 0;   //seconds counter to show total time .. it increases everytime the timer1 ticks.
private void timer1_Tick(object sender, EventArgs e)
{
    long speed = sentBytes - prevSentBytes ;  //here's the Transfer-Rate or Speed
    prevSentBytes = sentBytes ;
    labelSpeed.Text = CnvrtUnit(speed) + "/S";   //display the speed like (100 kb/s) to a label
    if (speed > 0)                //considering that the speed would be 0 sometimes.. we avoid dividing on 0 exception
    {
        totalSeconds++;     //increasing total-time
        labelTime.Text = TimeToText(TimeSpan.FromSeconds((sizeAll - sumAll) / speed));
        //displaying time-left in label
        labelTotalTime.Text = TimeToText(TimeSpan.FromSeconds(totalSeconds));
        //displaying total-time in label
    }
}

private string TimeToText(TimeSpan t)
{
    return string.Format("{2:D2}:{1:D2}:{0:D2}", t.Seconds, t.Minutes, t.Hours);
}

private string CnvrtUnit(long source)
{
    const int byteConversion = 1024;
    double bytes = Convert.ToDouble(source);

    if (bytes >= Math.Pow(byteConversion, 3)) //GB Range
    {
        return string.Concat(Math.Round(bytes / Math.Pow(byteConversion, 3), 2), " GB");
    }
    else if (bytes >= Math.Pow(byteConversion, 2)) //MB Range
    {
        return string.Concat(Math.Round(bytes / Math.Pow(byteConversion, 2), 2), " MB");
    }
    else if (bytes >= byteConversion) //KB Range
    {
        return string.Concat(Math.Round(bytes / byteConversion, 2), " KB");
    }
    else //Bytes
    {
        return string.Concat(bytes, " Bytes");
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文