#c #timeout #packets
#c #тайм-аут #пакеты
Вопрос:
Для проекта компьютерных сетей мы пишем ftp-сервер на c с различными протоколами window. У нас возникли проблемы с реализацией рабочей функции тайм-аута. Суть этого заключается в том, чтобы установить временную метку на момент передачи пакета, и если «подтверждение» не восстанавливается в течение определенного промежутка времени (скажем, 2,5 миллисекунд), повторно передать пакет. В настоящее время мы используем clock_gettime()
функцию для получения текущего времени и временной метки пакета.
Вот цикл while, с которым у нас возникают проблемы:
while(packet_sync_array[prev].recieved ==0 amp;amp; t==0)
{
clock_gettime(CLOCK_PROCESS_CPUTIME_ID,amp;timeout2);
currtime = timeout2.tv_nsec;
cout << "Is currtime: "<<currtime<< " - ptimeout " << ptimeout
<< " = " << (currtime - ptimeout) << " > "
<< (connection_parameters->timeoutInterval)*1000 << "?" << endl;
if((currtime - ptimeout)>((connection_parameters->timeoutInterval)*1000))
{
t = 1;
cout << "Prev PACKET TIMEDOUT" << endl;
cout << "Is currtime: "<<currtime<< " - ptimeout " << ptimeout
<< " = " << (currtime - ptimeout) << " > "
<< (connection_parameters->timeoutInterval)*1000 << "?" << endl;
}
}
Где ptimeout
— время отправки пакета и connection_parameters->timeoutInterval
— интервал тайм-аута. Проблема в том, что, поскольку ptimeout
это длинное целочисленное представление времени, иногда это очень большое значение (например, 999715992). Это означает, что он никогда не сможет определить, наступил ли тайм-аут, потому что текущее время в наносекундах будет равно 0, прежде чем значение станет достаточно большим.
Кто-нибудь еще сталкивался с этими проблемами синхронизации в c и у него есть возможное решение?
Спасибо!
Редактировать:
Спасибо за быстрые ответы! Я смог кое-что выяснить. Изменение цикла while, чтобы проверить, будет ли тайм-аут временная метка больше допустимого размера интервала long, позволяет мне посмотреть, получит ли clock_gettime откат к нулю перед сравнением. Зная это, я проверил, соответствует ли текущее время > (интервал тайм-аута — (максимально длинное значение int val — отметка времени)). Это допускает тайм-аут до 1 секунды, которого должно быть достаточно для решения этой проблемы. Если кто-нибудь думает, что у них есть лучшее решение, дайте мне знать! Спасибо! Вот код для тех, кому интересно:
if(((999999998-ptimeout)< (connection_parameters->timeoutInterval)*1000)amp;amp;(currtime - ptimeout)<0){
if(currtime > (((connection_parameters->timeoutInterval)*1000)-(999999998-ptimeout))){
t = 1;
cout << "this wrapped since " << currtime << " " << (connection_parameters->timeoutInterval)*1000 << "is bigger than 999999999 and then timed out" << endl;
cout << "curr time " << currtime << "is bigger than" << endl;
cout << (connection_parameters->timeoutInterval)*1000 << endl;
cout << "-" << endl;
cout << (999999998-ptimeout) << endl;
cout << "---------------------------" << endl;
cout << (((connection_parameters->timeoutInterval)*1000)-(999999998-ptimeout)) << endl;
cout << "Prev PACKET TIMEDOUT" << endl;
cout << "Is currtime: "<<currtime<< " - ptimeout " << ptimeout << " = " << (currtime - ptimeout) << " > " << (connection_parameters->timeoutInterval)*1000 << "?" << endl;
}
}
else if((currtime - ptimeout)>((connection_parameters->timeoutInterval)*1000)){
t = 1;
cout << "Prev PACKET TIMEDOUT" << endl;
cout << "Is currtime: "<<currtime<< " - ptimeout " << ptimeout << " = " << (currtime - ptimeout) << " > " << (connection_parameters->timeoutInterval)*1000 << "?" << endl;
}
Комментарии:
1. Я, конечно, не профи в сетевых вещах, но я почти уверен, что TCP / IP позаботится об обработке потерянных пакетов. Почему вы не полагаетесь на это?
2. @Joce они бы ничего не узнали о сетевых протоколах, если бы просто использовали предварительно упакованный 🙂
3. @Joce: «Для проекта компьютерных сетей мы пишем ftp-сервер на c с различными оконными протоколами». — «окно» будет означать временное окно для повторной отправки; они намеренно переопределяют часть функциональности TCP, чтобы узнать, как это сделать.
4. @Jeremy @Tony Видишь ли, я ничего не знаю о сети! 🙂
Ответ №1:
возможно, вы захотите изменить свой код, чтобы сказать:
// time in microseconds
currtime = timeout2.tv_sec * 1000000 timeout2.tv_nsec / 1000;
Просто убедитесь, что вы не получаете никаких переполнений целых чисел! Вероятно, хорошей идеей будет явно преобразовать, например, в 64-битное целое число.
Кроме того, вы, скорее всего, хотите, чтобы тайм-аут был по крайней мере на порядок больше 2,5 миллисекунд, возможно, больше. Ваш временной интервал в операционной системе, скорее всего, составит где-то около 17 миллисекунд, например, не говоря уже о задержках в сети.
Ответ №2:
Вам нужно посмотреть как на tv_sec
, так и на tv_nsec
компоненты timespec
объекта, который clock_gettime
заполняет. Ваше ptimeout
поле должно быть timespec
, а не целым числом. Вам придется писать функции для выполнения математики над timespec
объектами, я не думаю, что есть что-то запасное.