How to Throttle the Bandwidth of a Socket Connection in C

How do you throttle the bandwidth of a socket connection in C?

The problem with sleeping a constant amount of 1 second after each transfer is that you will have choppy network performance.

Let BandwidthMaxThreshold be the desired bandwidth threshold.

Let TransferRate be the current transfer rate of the connection.

Then...

If you detect your TransferRate > BandwidthMaxThreshold then you do a SleepTime = 1 + SleepTime * 1.02 (increase sleep time by 2%)

Before or after each network operation do a
Sleep(SleepTime)

If you detect your TransferRate is a lot lower than your BandwidthMaxThreshold you can decrease your SleepTime. Alternatively you could just decay/decrease your SleepTime over time always. Eventually your SleepTime will reach 0 again.

Instead of an increase of 2% you could also do an increase by a larger amount linearly of the difference between TransferRate - BandwidthMaxThreshold.

This solution is good, because you will have no sleeps if the user's network is already not as high as you would like.

C Linux Bandwidth Throttling of Application

It seems like this could be most directly solved by calculating the throttle sleep time in the send thread. I'm not sure I see the benefit of another thread to do this work.

Here is one way to do this:

Select a time window in which you will measure your send rate. Based on your target bandwidth this will give you a byte maximum for that amount of time. You can then check to see if you have sent that many bytes after each sendto(). If you do exceed the byte threshold then sleep until the end of the window in order to perform the throttling.

Here is some untested code showing the idea. Sorry that clock_gettime and struct timespec add some complexity. Google has some nice code snippets for doing more complete comparisons, addition, and subtraction with struct timespec.

#define MAX_BYTES_PER_SECOND (128L * 1024L)
#define TIME_WINDOW_MS 50L
#define MAX_BYTES_PER_WINDOW ((MAX_BYTES_PER_SECOND * TIME_WINDOW_MS) / 1000L)

#include <time.h>
#include <stdlib.h>

int foo(void) {
struct timespec window_start_time;

size_t bytes_sent_in_window = 0;
clock_gettime(CLOCK_REALTIME, &window_start_time);

while (1) {
size_t bytes_sent = sendto(sock, buff, strlen(buff), 0, (struct sockaddr *) &sin, sizeof(sin));
if (bytes_sent < 0) {
// error handling
} else {
bytes_sent_in_window += bytes_sent;

if (bytes_sent_in_window >= MAX_BYTES_PER_WINDOW) {
struct timespec now;
struct timespec thresh;

// Calculate the end of the window
thresh.tv_sec = window_start_time.tv_sec;
thresh.tv_nsec = window_start_time.tv_nsec;
thresh.tv_nsec += TIME_WINDOW_MS * 1000000;
if (thresh.tv_nsec > 1000000000L) {
thresh.tv_sec += 1;
thresh.tv_nsec -= 1000000000L;
}

// get the current time
clock_gettime(CLOCK_REALTIME, &now);

// if we have not gotten to the end of the window yet
if (now.tv_sec < thresh.tv_sec ||
(now.tv_sec == thresh.tv_sec && now.tv_nsec < thresh.tv_nsec)) {

struct timespec remaining;

// calculate the time remaining in the window
// - See google for more complete timespec subtract algorithm
remaining.tv_sec = thresh.tv_sec - now.tv_sec;
if (thresh.tv_nsec >= now.tv_nsec) {
remaining.tv_nsec = thresh.tv_nsec - now.tv_nsec;
} else {
remaining.tv_nsec = 1000000000L + thresh.tv_nsec - now.tv_nsec;
remaining.tv_sec -= 1;
}

// Sleep to end of window
nanosleep(&remaining, NULL);
}

// Reset counters and timestamp for next window
bytes_sent_in_window = 0;
clock_gettime(CLOCK_REALTIME, &window_start_time);
}
}
}
}

Limiting max speed of sockets

If you want to limit the download speed to 1 MB per second, manage your recv() calls in such a way that you do not recv() more than 1 MB in a single second. Once you have read the maximum 1 MB, throttle the thread (using ThreadSleep) until the next second. That's just a simple approach.

Bandwidth throttling in c++ application

You can try the below techniques,

  1. You can define a desired data transfer rate and a current transfer rate. Current transfer rate depends upon the number of bytes that you can per sec send/receive to/from the cloud, you can increase/decrease the Current transfer rate by a scale factor X but this should not increase beyond desired transfer rate. You can make a custom class on socket class to make your read/write functions.

  2. Second one is a predefined amount of data for only which you will execute a read/write operation on the socket. You can consider this amount of data as a unit/token which qualifies for a read/write operation. This technique also you can add to your custom class.

Socket gets throttled after certain amount of time

It is probably your code, but it's difficult for us to say as it's incomplete.

I wrote up my own set of best practices in a .NET TCP/IP FAQ - after many, many years of TCP/IP experience. I recommend you start with that.

P.S. I reserve the term "packet" for packets on-the-wire. A TCP app has no control over packets. I use the term "message" for application-protocol-level messages. I think this reduces confusion, especially for newcomers.

How does bandwidth limiting (with, say, ipfw) work?

All bandwidth limiters work on a simple principle – by filtering (dropping) packets. The implementation however is much more complex and require good knowledge of the TCP/IP stack and the consequences of filtering different types of traffic.

Bandwidth limiters are modeled on something called a token bucket. Tokens (that represent the data to be sent or received) are added to the bucket on regular time intervals. Since the bucket has a limited capacity if the bucket is full, new tokens are discarded (they overflow). This bucket is used to manage the amount of traffic. If there is enough tokens in the bucket the number of tokens is reduced for appropriate amount (proportional to the size of the packet) and the packet is sent or received. If there are not enough tokens in the bucket the packet is discarded. This is a basic explanation, read more on wiki or some other resource.

There are two basic kinds of traffic amount management — policing and shaping. The basic difference between the two is that a shaper has a queue or a buffer that can hold some amount of data. If the packets can't be sent immediately due to low number of tokens packets are placed in this buffer and are sent after there is a enough tokens. This technique is commonly used for outgoing traffic while the policing is used for incoming traffic.

After that you should want to know more about different token bucket mechanisms, how to avoid global synchronization of TCP flows, what are the effects of RED/WRED on non-TCP traffic, and a lot of other stuff linked to queues and QoS. In other words I think that satisfying a dependency is more easier than implementing all this so I suggest you use the tools that already work and build what you need on top of them.



Related Topics



Leave a reply



Submit