Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>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.</p> <p>Here is one way to do this:</p> <p>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.</p> <p>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.</p> <pre><code>#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 &lt;time.h&gt; #include &lt;stdlib.h&gt; int foo(void) { struct timespec window_start_time; size_t bytes_sent_in_window = 0; clock_gettime(CLOCK_REALTIME, &amp;window_start_time); while (1) { size_t bytes_sent = sendto(sock, buff, strlen(buff), 0, (struct sockaddr *) &amp;sin, sizeof(sin)); if (bytes_sent &lt; 0) { // error handling } else { bytes_sent_in_window += bytes_sent; if (bytes_sent_in_window &gt;= 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 &gt; 1000000000L) { thresh.tv_sec += 1; thresh.tv_nsec -= 1000000000L; } // get the current time clock_gettime(CLOCK_REALTIME, &amp;now); // if we have not gotten to the end of the window yet if (now.tv_sec &lt; thresh.tv_sec || (now.tv_sec == thresh.tv_sec &amp;&amp; now.tv_nsec &lt; 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 &gt;= 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(&amp;remaining, NULL); } // Reset counters and timestamp for next window bytes_sent_in_window = 0; clock_gettime(CLOCK_REALTIME, &amp;window_start_time); } } } } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload