应用çLinux的带宽限制 [英] C Linux Bandwidth Throttling of Application

查看:189
本文介绍了应用çLinux的带宽限制的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有什么办法,我可以尝试扼杀回发送 / 的sendto()功能的循环中。我创造了我的网络端口扫描程序,我尝试两种方法,但他们似乎只在本地工作(他们的工作时,我测试他们我家的机器上,但是当我尝试对它们进行测试另一台机器上它并不想创造适当的油门)。

What are some ways I can try to throttle back a send/sendto() function inside a loop. I am creating a port scanner for my network and I tried two methods but they only seem to work locally (they work when I test them on my home machine but when I try to test them on another machine it doesn't want to create appropriate throttles).

我本来解析的/ proc /净的/ dev ,并在属性中的发送的字节数读,立足我的睡眠时间关闭该。在本地,只要我试了一下另一台服务器上还与的/ proc /净的/ dev 这没'工作(睡眠延迟进行调整,调整带宽的流量),但不像是会被调整数据的权利。我跑了 dstat 一台机器上我是本地扫描,它是输出到多的数据快。

I was originally parsing /proc/net/dev and reading in the "bytes sent" attribute and basing my sleep time off that. That worked locally (the sleep delay was adjusting to adjust the flow of bandwidth) but as soon as I tried it on another server also with /proc/net/dev it didn't seem to be adjusting data right. I ran dstat on a machine I was locally scanning and it was outputting to much data to fast.

然后我试图跟踪多少字节我总共将派遣并将其添加到我的带宽线程将读取并计算睡眠定时器 total_sent 变量。这也工作我的本地机器上,但是当我试图在服务器上有人说,这只是发送每次1-2我的带宽线程将检查 total_sent 让我的包带宽线程减少睡眠为0,但即使在0 total_sent 变量没有增加,由于减少了睡眠时间,而是保持不变。

I then tried to keep track of how many bytes total I was sending and adding it to a total_sent variable which my bandwidth thread would read and compute a sleep timer for. This also worked on my local machine but when I tried it on a server it was saying that it was only sending 1-2 packets each time my bandwidth thread would check total_sent making my bandwidth thread reduce sleep to 0, but even at 0 the total_sent variable did not increase due to the reduced sleep time but instead stayed the same.

总的来说,我想一个办法来监视的Linux计算机的带宽和计算睡眠时间,我可以传递到 usleep()函式之前或之后每次我的发送 / 的sendto()插座调用油门回的带宽。

Overall I am wanting a way to monitor bandwidth of the Linux computer and calculate a sleep time I can pass into usleep() before or after each of my send/sendto() socket calls to throttle back the bandwidth.

编辑:一些其他的事情我忘了提的是,我有一个计算的机器上传速度的SPEEDTEST功能,我有2个线程。 1线程调整基于带宽使用情况和线程2的全球睡眠定时将数据包发送到远程计算机上的端口来测试,如果他们是开放的,指纹它们(现在我只是用UDP数据包以的sendto()来测试这一切)。

some other things I forgot to mention is that I do have a speedtest function that calculates upload speed of the machine and I have 2 threads. 1 thread adjusts a global sleep timer based on bandwidth usage and thread 2 sends the packets to the ports on a remote machine to test if they are open and to fingerprint them (right now I am just using udp packets with a sendto() to test this all).

我如何能实现带宽限制为通过发送 / 的sendto()通话 usleep()函式

How can I implement bandwidth throttling for a send/sendto() call using usleep().

编辑:这里是code为我的带宽监控线程。不要担心自己对结构的东西,它只是我的将数据传递到线程的方式。

Here is the code for my bandwidth monitoring thread. Don't concern yourself about the structure stuff, its just my way of passing data to a thread.

void *bandwidthmonitor_cmd(void *param)
{
  int i = 0;
  double prevbytes = 0, elapsedbytes = 0, byteusage = 0, maxthrottle = 0;

  //recreating my param struct i passed to the thread
  command_struct bandwidth = *((command_struct *)param);
  free(param);

  //set SLEEP (global variable) to a base time in case it was edited and not reset
  SLEEP = 5000;

  //find the maximum throttle speed in kb/s (takes the global var UPLOAD_SPEED
  //which is in kb/s and times it by how much bandwidth % you want to use
  //and devides by 100 to find the maximum in kb/s
  //ex: UPLOAD_SPEED = 60, throttle = 90, maxthrottle = 54
  maxthrottle = (UPLOAD_SPEED * bandwidth.throttle) / 100;
  printf("max throttle: %.1f\n", maxthrottle);

  while(1)
  {
      //find out how many bytes elapsed since last polling of the thread
      elapsedbytes = TOTAL_BYTES_SEND - prevbytes;
      printf("elapsedbytes: %.1f\n", elapsedbytes);

      //set prevbytes to our current bytes so we can have results next loop
      prevbytes = TOTAL_BYTES_SEND;

      //convert our bytes to kb/s
      byteusage = 8 * (elapsedbytes / 1024);

      //throttle control to make it adjust sleep 20 times every 30~ 
      //iterations of the loop
      if(i & 0x40)
      {
           //adjust SLEEP by 1.1 gain
           SLEEP += (maxthrottle - byteusage) * -1.1;//;


           if(SLEEP < 0){
               SLEEP = 0;
           }
           printf("sleep:%.1f\n\n", SLEEP);
      }

      //sleep the thread for a short bit then start the process over
      usleep(25000);
      //increment variable i for our iteration throttling
      i++;
  }

}

我的发送线程只是一个简单的的sendto()常规在而(1)循环发送UDP数据包进行测试。 袜子是我的的sockfd BUFF 是一个64字节的字符阵充满了A和我SOCKADDR_IN

My sending thread is just a simple sendto() routine in a while(1) loop sending udp packets for testing. sock is my sockfd, buff is a 64 byte character array filled with "A" and sin is my sockaddr_in.

  while(1)
  {
    TOTAL_BYTES_SEND += 64;

    sendto(sock, buff, strlen(buff), 0, (struct sockaddr *) &sin, sizeof(sin))


    usleep(SLEEP);
  }

我知道我的socket函数工作,因为我可以看到 dstat 我的本地计算机上的使用和远程计算机。该带宽code ++工程,我的本地系统上(所有变量的变化,因为他们应该),但我想在经过字节不会改变测试服务器上(总是64/128每个线程的迭代),并导致睡眠节流下降到0,这在理论上使整机速度较快,但发送的数据包甚至与睡眠等同于0 elapsedbytes保持64 / 128。我也带过$ C $光盘if语句检查函数返回-1和的printf <提醒我在的sendto()功能/ code> -ing错误code,但也一直没有之一,我已经做了测试。

I know my socket functions work because I can see the usage in dstat on my local machine and the remote machine. This bandwidth code works on my local system (all the variables change as they should) but on the server I tried testing on elapsed bytes does not change (is always 64/128 per iteration of the thread) and results in SLEEP throttling down to 0 which should in theory make the machine send packets faster but even with SLEEP equating to 0 elapsedbytes remain 64/128. I've also encoded the sendto() function inside a if statement checking for the function returning -1 and alerting me by printf-ing the error code but there hasn't been one in the tests I've done.

推荐答案

看起来这可以通过计算发送线程油门睡眠时间最直接的解决。我不知道我看到另一个线程的好处做这项工作。

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:

选择您将在其中衡量你的发送速率的时间窗口。根据你的目标的带宽这会给你一个字节的最大的时间量。然后,您可以检查是否已发送,每个SENDTO后的字节数()。如果你这样做超过字节阈值,则睡到窗口,以便执行节流结束。

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.

下面是显示这一想法的未经检验的code。遗憾的是,clock_gettime和结构的timespec增加一些复杂性。谷歌有一些不错的code片段与结构的timespec做更完整的比较,加法和减法。

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

这篇关于应用çLinux的带宽限制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆