Создать метку времени NTP от gettimeofday - PullRequest
1 голос
/ 15 апреля 2010

Мне нужно вычислить метку времени NTP, используя gettimeofday. Ниже, как я сделал это с комментариями к методу. Выглядите хорошо, ребята? (минус проверка ошибок). Кроме того, вот ссылка codepad .

#include <unistd.h>
#include <sys/time.h>

const unsigned long EPOCH = 2208988800UL; // delta between epoch time and ntp time
const double NTP_SCALE_FRAC = 4294967295.0; // maximum value of the ntp fractional part

int main()
{
  struct timeval tv;
  uint64_t ntp_time;
  uint64_t tv_ntp;
  double tv_usecs;

  gettimeofday(&tv, NULL);
  tv_ntp = tv.tv_sec + EPOCH;

  // convert tv_usec to a fraction of a second
  // next, we multiply this fraction times the NTP_SCALE_FRAC, which represents
  // the maximum value of the fraction until it rolls over to one. Thus,
  // .05 seconds is represented in NTP as (.05 * NTP_SCALE_FRAC)
  tv_usecs = (tv.tv_usec * 1e-6) * NTP_SCALE_FRAC;

  // next we take the tv_ntp seconds value and shift it 32 bits to the left. This puts the 
  // seconds in the proper location for NTP time stamps. I recognize this method has an 
  // overflow hazard if used after around the year 2106
  // Next we do a bitwise OR with the tv_usecs cast as a uin32_t, dropping the fractional
  // part
  ntp_time = ((tv_ntp << 32) | (uint32_t)tv_usecs);
}

Ответы [ 2 ]

1 голос
/ 20 мая 2012
extern uint64_t tvtontp64(struct timeval *tv) {
    uint64_t ntpts;

    ntpts = (((uint64_t)tv->tv_sec + 2208988800u) << 32) + ((uint32_t)tv->tv_usec * 4294.967296);

    return (ntpts);
}

Я использую 4294,967296, а не ... 5, так как это отношение к общему количеству 0 необходимо подсчитать 4294967296 тиков в секунду или 4294,967296 на использование. Это легко проверить, поскольку 1000000 пользователей будет переполнением [в секундах], диапазон тиков должен быть от 0 до (1000000-1).

Это упрощение и подходит для моих целей Уникальные локальные IPv6-адреса одноадресной рассылки [RFC4193]

1 голос
/ 15 апреля 2010

Нет необходимости использовать uint64_t здесь - unsigned long long гарантированно имеет ширину не менее 64 бит.

Вам также не нужно переходить к double и обратно, поскольку NTP_SCALE_FRAC * 1000000 легко поместится в unsigned long long.

EPOCH должно быть unsigned long long, а не unsigned long, так что добавление с tv.tv_sec не переносится.

Всего:

const unsigned long long EPOCH = 2208988800ULL;
const unsigned long long NTP_SCALE_FRAC = 4294967296ULL;

unsigned long long tv_to_ntp(struct timeval tv)
{
    unsigned long long tv_ntp, tv_usecs;

    tv_ntp = tv.tv_sec + EPOCH;
    tv_usecs = (NTP_SCALE_FRAC * tv.tv_usec) / 1000000UL;

    return (tv_ntp << 32) | tv_usecs;
}
...