Question

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);
        }
    }
Was it helpful?

Solution 2

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

OTHER TIPS

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).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top