delphiindy

How do I reset a buffer of indy UDP client?


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 ?


Solution

  • 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.