Какими способами я могу попытаться ограничить функцию send
/sendto()
внутри цикла. Я создаю сканер портов для своей сети, и я попробовал два метода, но они, кажется, работают только локально (они работают, когда я тестирую их на своей домашней машине, но когда я пытаюсь проверить их на другой машине, он не хочет создавать соответствующие дроссели).
метод 1
Первоначально я анализировал /proc/net/dev
и читал атрибут «отправлено байтов» и основывал свое время сна на этом. Это работало локально (задержка сна настраивалась для регулировки потока полосы пропускания), но как только я попробовал это на другом сервере, также с /proc/net/dev
, похоже, данные не корректировались правильно. Я запустил dstat
на машине, которую сканировал локально, и она выдавала слишком много данных слишком быстро.
метод 2
Затем я попытался отследить общее количество отправляемых байтов и добавить его в переменную total_sent
, которую мой поток полосы пропускания будет читать и вычислять таймер сна. Это также работало на моем локальном компьютере, но когда я попробовал это на сервере, он сказал, что он отправляет только 1-2 пакета каждый раз, когда мой поток пропускной способности проверяет total_sent
, заставляя мой поток пропускной способности уменьшать сон до 0, но даже при 0 total_sent
переменная не увеличилась из-за сокращения времени сна, а осталась неизменной.
В целом, мне нужен способ отслеживать пропускную способность компьютера с Linux и вычислять время сна, которое я могу передать в usleep()
до или после каждого из моих вызовов сокета send
/sendto()
, чтобы уменьшить пропускную способность.
Редактировать: некоторые другие вещи, которые я забыл упомянуть, это то, что у меня есть функция speedtest, которая вычисляет скорость загрузки машины, и у меня есть 2 потока. Поток 1 настраивает глобальный таймер сна на основе использования полосы пропускания, а поток 2 отправляет пакеты на порты на удаленной машине, чтобы проверить, открыты ли они, и снять с них отпечаток (сейчас я просто использую пакеты udp с sendto()
, чтобы проверить все это ).
Как я могу реализовать регулирование полосы пропускания для вызова send
/sendto()
с помощью usleep()
.
Редактировать. Вот код для моего потока мониторинга пропускной способности. Не беспокойтесь о структуре, это просто мой способ передачи данных в поток.
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()
процедура в цикле while(1)
, отправляющая udp-пакеты для тестирования. sock
— это мой sockfd
, buff
— это 64-байтовый массив символов, заполненный «A», а sin
— это my sockaddr_in
.
while(1)
{
TOTAL_BYTES_SEND += 64;
sendto(sock, buff, strlen(buff), 0, (struct sockaddr *) &sin, sizeof(sin))
usleep(SLEEP);
}
Я знаю, что мои функции сокета работают, потому что я вижу использование в dstat
на моей локальной машине и на удаленной машине. Этот код пропускной способности работает в моей локальной системе (все переменные меняются как надо), но на сервере, который я пробовал тестировать на прошедших байтах, не меняется (всегда 64/128 на итерацию потока) и приводит к SLEEP
дросселированию до 0 что теоретически должно заставить машину отправлять пакеты быстрее, но даже с SLEEP
, равным 0 прошедшим байтам, остается 64/128. Я также закодировал функцию sendto()
внутри оператора if, проверяющего функцию, возвращающую -1, и предупреждающую меня printf
-кодом ошибки, но в тестах, которые я проводил, ее не было.
if((TOTAL_BYTES_SEND += sockto(sock,...)) == -1) { printf("error"); }
, и ошибок нет, и теперь я получаю реальный вывод функции sendto(), но на сервере, которым я владею, с загрузкой 4000 КБ/с, я все еще получаю очень низкие истекшие байты, что вызывает SLEEP становится 0, что не увеличивает количество истекших байтов, как на моем сервере (режим сна регулируется вверх и вниз, чтобы поддерживать кбит/с, рассчитанный как maxthrottle) - person randy newfield   schedule 26.11.2012