UTC отметка времени в Windows - PullRequest
1 голос
/ 18 мая 2010

У меня есть буфер с меткой времени UTC в C, я транслирую этот буфер через каждые десять секунд. Проблема в том, что разница во времени между двумя пакетами не согласована. После 5-10 итераций разница во времени становится 9, 11, а затем снова 10. Пожалуйста, помогите мне разобраться с этой проблемой.

Я использую <time.h> для времени UTC.

Ответы [ 2 ]

3 голосов
/ 18 мая 2010

Если ваша временная метка имеет разрешение всего 1 секунду, то всегда будет неопределенность +/- 1 в младшей значащей цифре (т.е. в этом случае +/- 1 секунда).

Уточнение: если у вас разрешение только 1 секунда, тогда ваши значения времени равны quantized. Реальное время, t, представленное таким квантованным значением, имеет диапазон t..t+0.9999. Если взять разницу двух таких времен, t0 и t1, то максимальная ошибка в t1-t0 равна -0.999..+0.999, что при квантовании составляет +/-1 секунду. Так что в вашем случае вы ожидаете увидеть разницу значений в диапазоне 9..11 секунд.

1 голос
/ 18 мая 2010

Поток, который спит в течение X миллисекунд, не гарантированно спит именно столько миллисекунд. Я предполагаю, что у вас есть утверждение, которое выглядит примерно так:

while(1) {
  ...
  sleep(10); // Sleep for 10 seconds.
  // fetch timestamp and send
}

Вы получите более точный показатель времени, если будете спать в течение более коротких периодов (скажем, 20 миллисекунд) в циклической проверке до истечения времени. Когда вы спите в течение 10 секунд, ваш поток перемещается дальше от непосредственного приоритета планирования базовой ОС.

Вы также можете принять во внимание, что время, необходимое для отправки меток времени, может варьироваться в зависимости от состояния сети и т. Д., Если вы делаете цикл sleep (10) -> send -> sleep (10), время взятые для отправки будут добавлены в следующий сон (10) в реальном выражении.

Попробуйте что-то вроде этого (прости меня, мой C немного ржавый):

bool expired = false;
double last, current;
double t1, t2;
double difference = 0;

while(1) {
   ...
   last = (double)clock();
   while(!expired) {
      usleep(200); // sleep for 20 milliseconds
      current = (double)clock();
      if(((current - last) / (double)CLOCKS_PER_SEC) >= (10.0 - difference))
        expired = true;
   }
   t1 = (double)clock();
   // Set and send the timestamp.
   t2 = (double)clock();
   //
   // Calculate how long it took to send the stamps.
   // and take that away from the next sleep cycle.
   //
   difference = (t2 - t1) / (double)CLOCKS_PER_SEC;
   expired = false;
 }

Если вас не беспокоит использование стандартной библиотеки C, вы можете посмотреть на использование функций таймера высокого разрешения для окон, таких как функции QueryPerformanceFrequency / QueryPerformanceCounter.

LONG_INTEGER freq;
LONG_INTEGER t2, t1;
//
// Get the resolution of the timer.
//
QueryPerformanceFrequency(&freq);

// Start Task.
QueryPerformanceCounter(&t1);

... Do something ....

QueryPerformanceCounter(&t2);

// Very accurate duration in seconds.
double duration = (double)(t2.QuadPart - t1.QuadPart) / (double)freq.QuadPart;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...