реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> Как получить время по протоколу NTP
viakon
сообщение Aug 15 2012, 08:08
Сообщение #1


Местный
***

Группа: Участник
Сообщений: 290
Регистрация: 9-12-05
Из: г. Пермь
Пользователь №: 12 002



Растолкуйте по простому SUBJ на уровне
1 посылаешь по 123 порту xxxxx
2 получаешь хххххх где xx часы xx минуты
Go to the top of the page
 
+Quote Post
scifi
сообщение Aug 15 2012, 08:32
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Гугл сломался?
Вот моя реализация клиента SNTP, может быть что-то полезное почерпнёте:
CODE
/**
* @file sntp.c
* @brief SNTP client / clock
*/

#include "sntp.h"
#include "event.h"
#include "systime.h"
#include "mcf5223xif.h"
#include "lwip/udp.h"
#include "assert_static.h"
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

#define SENDFAIL_TIMEOUT 5000 /* 5 seconds */
#define SENT_TIMEOUT 60000 /* 1 minute */
#define BADREPLY_TIMEOUT 60000 /* 1 minute */
#define VALID_TIMEOUT (8 * 3600000) /* 8 hours */

#define SECSPERMIN 60L
#define MINSPERHOUR 60L
#define HOURSPERDAY 24L
#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR)
#define SECSPERDAY (SECSPERHOUR * HOURSPERDAY)
#define DAYSPERWEEK 7
#define MONSPERYEAR 12

#define YEAR_BASE 1900
#define EPOCH_WDAY 1
#define EPOCH_YEARS_SINCE_LEAP 2
#define EPOCH_YEARS_SINCE_CENTURY 70
#define EPOCH_YEARS_SINCE_LEAP_CENTURY 370

#define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)

enum sntp_state
{
SNTP_INIT, SNTP_SENDFAIL, SNTP_SENT, SNTP_BADREPLY, SNTP_VALID
};

struct sntp_packet
{
uint8_t status;
uint8_t stratum;
uint8_t ppoll;
uint8_t precision;
uint32_t distance;
uint32_t dispersion;
uint32_t refid;
uint64_t reftime;
uint64_t org;
uint64_t rec;
uint64_t xmt;
};

static bool time_valid = false;
static enum sntp_state state = SNTP_INIT;
static int32_t last_time, link_time;
static struct udp_pcb* upcb;
static struct ip_addr server;
static uint_fast16_t port = 123;
static uint64_t startup_time; /* timestamp in UTC */
static int_fast16_t tz;

static uint64_t
ms2ts(uint64_t ms)
{
return ((ms / 1000) << 32) | (((ms % 1000) / 4) << 24);
}

static void recv(void *arg,
struct udp_pcb *upcb,
struct pbuf *p,
struct ip_addr *addr,
u16_t port)
{
if (p->len == sizeof(struct sntp_packet))
{
int i;
struct sntp_packet *ptr;
assert(p->len == p->tot_len); /* don't accept chained pbuf */
ptr = p->payload;
i = (ptr->status >> 3) & 7;
if ((i < 1) || (i > 4)) /* SNTP version 1..4 */
{
goto out;
}
i = ptr->status & 7;
if ((i != 4) && (i != 5)) /* mode 4 or 5: server or broadcast */
{
goto out;
}
if (ptr->stratum == 0)
{
goto out;
}
if (ptr->xmt == 0)
{
goto out;
}
startup_time = ptr->xmt - ms2ts(systime_ms64());
if (!time_valid)
{
time_valid = true;
event_trigger(EVENT_SNTPSYNC);
}
state = SNTP_VALID;
last_time = systime_ms32();
}
out:
pbuf_free(p);
}

void
sntp_enable(bool enable)
{
assert_static(BYTE_ORDER == BIG_ENDIAN);
if (enable)
{
if (upcb == 0)
{
err_t ret;
upcb = udp_new();
assert(upcb != 0);
ret = udp_bind(upcb, IP_ADDR_ANY, port);
if (ret != ERR_OK)
{
udp_remove(upcb);
upcb = 0;
}
else
{
udp_recv(upcb, recv, 0);
}
state = SNTP_INIT;
}
}
else if (upcb != 0)
{
udp_remove(upcb);
upcb = 0;
}
}

bool
sntp_isenabled(void)
{
return upcb != 0;
}

void
sntp_setserveraddr(const struct ip_addr *addr)
{
ip_addr_copy(server, *addr);
}

void
sntp_getserveraddr(struct ip_addr *addr)
{
ip_addr_copy(*addr, server);
}

void
sntp_setserverport(uint_fast16_t port_arg)
{
port = port_arg;
if (sntp_isenabled())
{
sntp_enable(false);
sntp_enable(true);
}
}

uint_fast16_t
sntp_getserverport(void)
{
return port;
}

void
sntp_settz(int_fast16_t tz_arg)
{
tz = tz_arg;
}

int_fast16_t
sntp_gettz(void)
{
return tz;
}

static void
send_request(void)
{
struct sntp_packet packet;
struct pbuf* psend;
memset(&packet, 0, sizeof(packet));
packet.status = (3 << 3) /* SNTP vesion 3 */
| (3 << 0); /* Mode: client */
psend = pbuf_alloc(PBUF_RAW, sizeof(packet), PBUF_REF);
if (psend != 0)
{
psend->payload = &packet;
state = (udp_sendto(upcb, psend, &server, port) == ERR_OK)
? SNTP_SENT : SNTP_SENDFAIL;
pbuf_free(psend);
}
last_time = systime_ms32();
}

void
sntp_poll(void)
{
if (mcf5223xif_link() == false)
{
link_time = systime_ms32();
}
else if (upcb != 0)
{
int32_t now, timeout;
now = systime_ms32();
if (abs(now - link_time) > 2000)
{
switch (state)
{
case SNTP_INIT: send_request(); return;
case SNTP_SENDFAIL: timeout = SENDFAIL_TIMEOUT; break;
case SNTP_SENT: timeout = SENT_TIMEOUT; break;
case SNTP_BADREPLY: timeout = BADREPLY_TIMEOUT; break;
case SNTP_VALID: timeout = VALID_TIMEOUT; break;
}
if (now - last_time > timeout)
{
send_request();
}
}
}
}

bool
sntp_valid(void)
{
return time_valid;
}

uint32_t
sntp_timestamp(void)
{
return time_valid ? (startup_time + ms2ts(systime_ms64())) >> 32 : 0;
}

static const uint8_t mon_lengths[2][MONSPERYEAR] =
{
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
} ;

static const int year_lengths[2] = { 365, 366 } ;

void
sntp_seconds2tm(uint32_t sec32, struct tm* res)
{
long days, rem;
int y;
int yleap;
const uint8_t *ip;
uint64_t sec;

sec = sec32 + 60 * tz;
if (((sec32 & 0x80000000UL) == 0) && (sec32 != 0))
{
sec += ((uint64_t)1 << 32);
}
days = sec / SECSPERDAY;
rem = sec % SECSPERDAY;

/* compute hour, min, and sec */
res->tm_hour = (int) (rem / SECSPERHOUR);
rem %= SECSPERHOUR;
res->tm_min = (int) (rem / SECSPERMIN);
res->tm_sec = (int) (rem % SECSPERMIN);

/* compute day of week */
if ((res->tm_wday = ((EPOCH_WDAY + days) % DAYSPERWEEK)) < 0)
{
res->tm_wday += DAYSPERWEEK;
}

/* compute year & day of year */
y = YEAR_BASE;
if (days >= 40542) /* days in years 1900..2010 inclusive */
{
days -= 40542;
y += 111;
}
if (days >= 0)
{
for (;;)
{
yleap = isleap(y);
if (days < year_lengths[yleap])
{
break;
}
y++;
days -= year_lengths[yleap];
}
}
else
{
do
{
--y;
yleap = isleap(y);
days += year_lengths[yleap];
}
while (days < 0);
}

res->tm_year = y - YEAR_BASE;
res->tm_yday = days;
ip = mon_lengths[yleap];
for (res->tm_mon = 0; days >= ip[res->tm_mon]; ++res->tm_mon)
{
days -= ip[res->tm_mon];
}
res->tm_mday = days + 1;
}

void
sntp_gettimestr(uint32_t timestamp, char *str)
{
if (timestamp != 0)
{
struct tm time;
sntp_seconds2tm(timestamp, &time);
sprintf(str, "%02d.%02d.%d %02d:%02d:%02d",
time.tm_mday,
time.tm_mon + 1,
time.tm_year + 1900,
time.tm_hour,
time.tm_min,
time.tm_sec);
}
else
{
strcpy(str, "00.00.0000 00:00:00");
}
}
Go to the top of the page
 
+Quote Post
viakon
сообщение Aug 15 2012, 08:49
Сообщение #3


Местный
***

Группа: Участник
Сообщений: 290
Регистрация: 9-12-05
Из: г. Пермь
Пользователь №: 12 002



гуглом все в порядке, просто выдаваемая им куча мусора огромна.

спасибо за пример просветление в мозгах подступаетsm.gif.
Go to the top of the page
 
+Quote Post
Pridnya
сообщение Dec 12 2016, 06:34
Сообщение #4


Частый гость
**

Группа: Свой
Сообщений: 142
Регистрация: 11-01-11
Из: Орел
Пользователь №: 62 159



Цитата(scifi @ Aug 15 2012, 11:32) *
Гугл сломался?

Еще один "велосипед". Не очень понятно, почему вы вместо функции strftime() стандартной библиотеки time.h пишете свою, делающую то же самое. Или не знали о её существовании? Какой смысл? И за 4 года никто не спросил и не поправил. В предыдущем посте кто-то даже просветлился. biggrin.gif А что еще написать на такую портянку, когда сразу не въехал.
Код
time_t rawtime = 1480685759; // Fri, 02 Dec 2016 13:35:59 GMT
struct tm * timeinfo;
timeinfo = (struct tm*)localtime(&rawtime);
char buffer [80];
strftime (buffer,80,"%d.%m.%Y %X",timeinfo);
puts (buffer); // 02.12.2016 13:35:59


Ладно бы вы использовали какой-нибудь R32C Renesas и их компилятор NC100 в котором стандартная библиотека time.h вообще не реализована, но вы же отвечаете в теме по ARM, а в ARMCC хорошая библиотека.

PS: И UnixTime в структуру руками не нужно переписывать (у вас 70 строк кода???):
Код
void sntp_seconds2tm(uint32_t sec32, struct tm* res)...

Из NTP timestamp вычитаем разницу в секундах между 1970-1900 годами и используем стандартную функцию.

PPS: Дальше черпать неохота, т.к. почерпнуть нечего.

Сообщение отредактировал IgorKossak - Dec 13 2016, 19:47
Причина редактирования: бездумное цитирование
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 20th July 2025 - 17:08
Рейтинг@Mail.ru


Страница сгенерированна за 0.0139 секунд с 7
ELECTRONIX ©2004-2016