I noticed a little issue with Indy's TIdSNTP
:
If the timeout is less than actual network delay, when doing DateTime
request, the datagram is not received in timeout
time;
however this old datagram is kept in some internal buffer and next call to the DateTime
receives this old datagram, giving wrong time value.
var sntp1: TIdSNTP := TIdSNTP.Create;
sntp1.Host := 'pool.ntp.org';
sntp1.ReceiveTimeout := 5;
sntp1.DateTime;
Memo1.Lines.Add(Format(' delay: %d', [ round(sntp1.RoundTripDelay * MSecsPerDay) ]));
Application.ProcessMessages;
sleep(3000);
sntp1.ReceiveTimeout := 500;
sntp1.DateTime;
Memo1.Lines.Add(Format(' delay: %d', [ round(sntp1.RoundTripDelay * MSecsPerDay) ]));
The question is, how do I properly reset the buffer to clear old pending data, before next call to DateTime
?
You are reusing the same underlying socket for both TIdSNTP.DateTime
queries, which is why the packet is able to be cached inside the socket.
You should re-create the TIdSNTP
object each time, or at least close its current socket with TIdSNTP.Binding.CloseSocket()
so the next query will create a new socket.
You could try flushing the socket buffer manually, by reading directly from the TIdSNTP.Binding
socket until there is nothing left to read. But this is still a race condition if a new packet arrives after you flush but before you perform the next query. So better to just discard the socket altogether to throw away the current buffer.