Что нового

Получение даты и времени по протоколу NTP

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Функция довольно простая, если внимательно изучить работу протокола NTP (ссылка в комментариях). А так, просто указываем адрес NTP-сервера и получаем дату и время в виде структуры FILETIME (см. пример).

Код:
#Include <StructureConstants.au3>
#Include <Date.au3>

Func _NTP_FT($sServer, $fLocal = True)

;~	http://book.itep.ru/4/44/sntp4416.htm

	Local $tNTP = DllStructCreate('byte Header[4];byte RootDelay[4];byte RootDispersion[4];byte ReferenceIdentifier[4];byte ReferenceTimestamp[8];byte OriginateTimestamp[8];byte ReceiveTimestamp[8];byte TransmitTimestamp[8];byte KeyIdentifier[4];byte MessageDigest[16]')
	Local $tPacket = DllStructCreate('byte Packet[68]', DllStructGetPtr($tNTP))
	Local $bPacket = 0, $tFT, $tQW, $aSocket, $aResult

;~	0x1B000000 = 00011011 00000000 00000000 00000000b (LI = 00b VN = 011b Mode = 011b Stratum = 00000000b Poll = 00000000b Precision = 00000000b)
	$tNTP.Header = Binary('0x1B000000')
	UDPStartup()
	If @Error Then
		Return SetError(1, 0, 0)
	EndIf
	$aSocket = UDPOpen(TCPNameToIP($sServer), 123)
	If @Error Then
		; Nothing
	Else
		UDPSend($aSocket, $tPacket.Packet)
		If @Error Then
			; Nothing
		Else
			While 1
				$bPacket = UDPRecv($aSocket, 68, 1)
				If (@Error) Or ($bPacket) Then
					ExitLoop
				EndIf
				Sleep(100)
			WEnd
		EndIf
	EndIf
	UDPCloseSocket($aSocket)
	UDPShutdown()
	If Not $bPacket Then
		Return SetError(2, 0, 0)
	EndIf
	$tFT = DllStructCreate($tagFILETIME)
	If $fLocal Then
		$tQW = DllStructCreate('uint64 Timestamp')
	Else
		$tQW = DllStructCreate('uint64 Timestamp', DllStructGetPtr($tFT))
	EndIf
	$tPacket.Packet = $bPacket
;~	$tQW.Timestamp = _WinAPI_SwapDWord(DllStructGetData(DllStructCreate('uint', DllStructGetPtr($tNTP, 'TransmitTimestamp')), 1)) * 10000000 + 94354848000000000
	$tQW.Timestamp = Dec(StringMid(DllStructGetData($tNTP, 'TransmitTimestamp'), 3, 8), 2) * 10000000 + 94354848000000000
	If $fLocal Then
		$aResult = DllCall('kernel32.dll', 'bool', 'FileTimeToLocalFileTime', 'struct*', $tQW, "struct*", $tFT)
		If (@Error) Or (Not $aResult[0]) Then
			Return SetError(3, 0, 0)
		EndIf
	EndIf
	Return $tFT
EndFunc   ;==>_NTP_FT

$tFT = _NTP_FT('pool.ntp.org')

ConsoleWrite(_Date_Time_FileTimeToStr($tFT) & @CRLF)
 

Kasper

Знающий
Сообщения
70
Репутация
8
Не работает функция.
Проверял на этих серверах и везде получал пустой результат
pool.ntp.org
ntp1.stratum2.ru
ntp2.stratum2.ru
ntp1.stratum1.ru
ntp2.stratum1.ru
 
Автор
Yashied

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Только что проверил ваши сервера, все рабочие. Ищите проблему у себя. Возможно что-то блокирует 123-ий порт UDP.
 
Верх