|
|
![]() |
|
||
|
|
|||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Visual Basic Network Services SetSystemTime: SNTP Time Server Synchronization using Winsock |
|
| Posted: | Sunday February 03, 2002 |
| Updated: | Monday December 26, 2011 |
| Applies to: | VB4-32, VB5, VB6 |
| Developed with: | VB6, Windows XP |
| OS restrictions: | None, but see Comments below. |
| Author: | VBnet - Randy Birch, MSKB, Paul Hewson |
|
Related: |
WM_TIMECHANGE: Detect System Changes to the Date/Time RegQueryValueEx: Identify Time Zones by Time Zone Bias NetRemoteTOD: Get Time of Day Info for Local or Remote Machines SetSystemTime: Date and Time Synchronization to a Remote Server |
| Prerequisites |
| Network or DUN connection. |
|
|
Windows
XP, as part of enhanced Date/Time control panel functionality, provides
for automatic updating of the system date/time via connection to either
of a pair of Simple Network Time Protocol (SNTP) time servers that are
available on the Internet (time.windows.com and time.nist.gov). This is
the same functionality gained by issuing a NET TIME command.
Shown in the illustration is the result of calling the indicated time server using just the Winsock control provided with VB and the SetSystemTime API. The 32bit time stamp returned by SNTP servers is the number of seconds since midnight 1 January 1900 GMT, such that the time "1" is 12:00:01 am on January 1, 1900 GMT. Using a base of 1990, the SNTP time routines will serve until 2036.
About NTP Time Servers |
| BAS Module Code |
| None. |
|
|
| Form Code |
|
|
| To a form add a combo (Combo1), a list (List1), a Winsock control (Winsock1), and two command buttons (Command1, Command2), along with the following code: |
|
|
Option Explicit '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Copyright ©1996-2011 VBnet/Randy Birch, All Rights Reserved. ' Some pages may also contain other copyrights by the author. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ' Distribution: You can freely use this code in your own ' applications, but you may not reproduce ' or publish this code on any web site, ' online service, or distribute as source ' on any media without express permission. '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Dim sNTP As String 'the 32bit time stamp returned by the server
Dim TimeDelay As Single 'the time between the acknowledgement of
'the connection and the data received.
'we compensate by adding half of the round
'trip latency
Private Type SYSTEMTIME
wYear As Integer
wMonth As Integer
wDayOfWeek As Integer
wDay As Integer
wHour As Integer
wMinute As Integer
wSecond As Integer
wMilliseconds As Integer
End Type
Private Declare Function SetSystemTime Lib "kernel32" _
(lpSystemTime As SYSTEMTIME) As Long
Private Sub Form_Load()
With Combo1
.AddItem "time-a.timefreq.bldrdoc.gov"
.AddItem "time-b.timefreq.bldrdoc.gov"
.AddItem "time-c.timefreq.bldrdoc.gov"
.AddItem "utcnist.colorado.edu"
.AddItem "time-nw.nist.gov"
.AddItem "nist1.nyc.certifiedtime.com"
.AddItem "nist1.dc.certifiedtime.com"
.AddItem "nist1.sjc.certifiedtime.com"
.AddItem "nist1.datum.com"
.AddItem "ntp2.cmc.ec.gc.ca"
.AddItem "ntps1-0.uni-erlangen.de"
.AddItem "ntps1-1.uni-erlangen.de"
.AddItem "ntps1-2.uni-erlangen.de"
.AddItem "ntps1-0.cs.tu-berlin.de"
.AddItem "time.ien.it"
.AddItem "ptbtime1.ptb.de"
.AddItem "ptbtime2.ptb.de"
.ListIndex = 0
End With
End Sub
Private Sub Command1_Click()
'show routine's activity for debugging
With List1
If .ListCount > 0 Then .AddItem ""
.AddItem "target: " & Combo1.Text
.AddItem "opening connection"
End With
'clear the string used for incoming data
sNTP = Empty
'connect
With Winsock1
If .State <> sckClosed Then .Close
.RemoteHost = Combo1.Text
.RemotePort = 37 'port 37 is the timserver port
.Connect
End With
End Sub
Private Sub Command2_Click()
'opens the date/time window
Call Shell("rundll32.exe shell32.dll,Control_RunDLL timedate.cpl,,0", vbNormalFocus)
End Sub
Private Sub Winsock1_Connect()
List1.AddItem " winsock connection made"
End Sub
Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)
Dim sData As String
Winsock1.GetData sData, vbString
sNTP = sNTP & sData
List1.AddItem " data received: " & sData & " (" & bytesTotal & " bytes)"
End Sub
Private Sub Winsock1_Close()
On Error Resume Next
List1.AddItem " closing connection"
Winsock1.Close
List1.AddItem " sockets closed"
Call SyncSystemClock(sNTP)
End Sub
Private Sub SyncSystemClock(ByVal sTime As String)
Dim NTPTime As Double
Dim UTCDATE As Date
Dim dwSecondsSince1990 As Long
Dim ST As SYSTEMTIME
sTime = Trim(sTime)
If Len(sTime) = 4 Then
'since the data was returned in a string,
'format it back into a numeric value
NTPTime = Asc(Left$(sTime, 1)) * (256 ^ 3) + _
Asc(Mid$(sTime, 2, 1)) * (256 ^ 2) + _
Asc(Mid$(sTime, 3, 1)) * (256 ^ 1) + _
Asc(Right$(sTime, 1))
'and create a valid date based on
'the seconds since January 1, 1990
dwSecondsSince1990 = NTPTime - 2840140800#
UTCDATE = DateAdd("s", CDbl(dwSecondsSince1990), #1/1/1990#)
'fill a SYSTEMTIME structure with the appropriate values
With ST
.wYear = Year(UTCDATE)
.wMonth = Month(UTCDATE)
.wDay = Day(UTCDATE)
.wHour = Hour(UTCDATE)
.wMinute = Minute(UTCDATE)
.wSecond = Second(UTCDATE)
End With
'just shows what's happening
With List1
.AddItem " beginning system clock synchronization"
.AddItem " data value (GMT): " & vbTab & NTPTime
.AddItem " sec since 1990 (GMT):" & vbTab & dwSecondsSince1990
.AddItem " system date (local) : " & vbTab & Now 'Date & " " & Time
.AddItem " synced date (GMT) : " & vbTab & UTCDATE
.AddItem " calling SetSystemTime"
End With
'and call the API with the new date & time
If SetSystemTime(ST) Then
List1.AddItem "clock synchronised succesfully"
List1.TopIndex = List1.NewIndex
Else
List1.AddItem "SetSystemTime failed. Clock not synchronised"
End If
Else
List1.AddItem "Time passed not valid. Clock not synchronised"
End If
End Sub
Private Sub Winsock1_Error(ByVal Number As Integer, _
Description As String, _
ByVal Scode As Long, _
ByVal Source As String, _
ByVal HelpFile As String, _
ByVal HelpContext As Long, _
CancelDisplay As Boolean)
With List1
.AddItem " error received: " & Description
.AddItem " error received: " & Number
End With
'if an error occurred, assure the socket is closed
If Number > 0 Then
If Winsock1.State <> sckClosed Then
Winsock1.Close
List1.AddItem "sockets closed"
Else
List1.AddItem "sockets closed"
End If
End If
End Sub |
| Comments |
|
The
Microsoft Knowledge Base contains a few articles particular to this
topic. Q216734 discusses How to Configure an Authoritative Time Server in Windows 2000. The information is of special interest to network admins who want to synchronize servers or workstations running Windows 2000 . Q224799, again for Win2k, covers the Basic Operation of the Windows Time Service. Network admins should also note that according to the MSDN, calling SetSystemTime under Windows NT, Windows 2000 or Windows XP enables the SE_SYSTEMTIME_NAME privilege before changing the system time. This privilege is disabled by default. |
|
|
|
|
|
|||||
|
|||||
|
|
|||||
|
Copyright ©1996-2011 VBnet and Randy Birch. All Rights Reserved. |
![]() |