На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Соблюдайте общие правила форума
Пожалуйста, выделяйте текст программы тегом [сode=pas] ... [/сode]. Для этого используйте кнопку [code=pas] в форме ответа или комбобокс, если нужно вставить код на языке, отличном от Дельфи/Паскаля.
Указывайте точные версии Delphi и используемых сетевых библиотек.

Не приветствуется поднятие старых тем. Если ваш вопрос перекликается со старой темой, то для вопроса лучше создать новую тему, а старую указать в первом сообщении с описанием взаимосвязи.

Внимание:
попытки открытия обсуждений реализации вредоносного ПО, включая различные интерпретации спам-ботов, наказывается предупреждением на 30 дней.
Повторная попытка - 60 дней. Последующие попытки бан.
Мат в разделе - бан на три месяца...

Полезные ссылки:
user posted image MSDN Library user posted image FAQ раздела user posted image Поиск по разделу user posted image Как правильно задавать вопросы


Выразить свое отношение к модераторам раздела можно здесь: user posted image Krid, user posted image Rouse_

Модераторы: Krid, Rouse_
  
> IdSNTPClient странная работа , непонятный глюк
    Мир вам. Подскажите, может кто сталкивался.
    На форму кидаю TidSNTP и таймер.
    Устанавливаю свойства:
    ExpandedWrap disabled
      idsntp.Host           := '192.168.0.73';
      idsntp.Port           := 1234;
      idsntp.ReciveTimeout  := 500; //1000;

    Таймер срабатывает с периодом в 10 секунд.
    В обработчике таймера происходит следующее:
    ExpandedWrap disabled
      if idsntp.datetime <> 0 then
       begin
      //caption := inttostr(idsntp.sendtime) + ' '+inttostr(idsntp.rectime);
        statuslabel.Caption        := 'Ok';
        rounddelaylabel.Caption    := inttostr(round (idsntp.RoundTripDelay * 24 * 3600 * 1000)) + ' ms';
        adjustingtimelabel.Caption := inttostr(round (idsntp.AdjustmentTime * 24 * 3600 * 1000)) + ' ms';

    Так вот, как правило, idsntp.datetime отрабатывает корректно и тогда значения RoundTripDelay лежат в интервале 4..300 мс.
    Но иногда/периодически возникает странная ситуация: idsntp.datetime отрабатывает вроде бы штатно, но RoundTripDelay составляет секунды, до 10 и более, и примерно на столько же увеличивается и AdjustmentTime. Обычно начинается с того, что первый при запуске программы вызов datetime отрабатывает с ошибкой(почему-то), а вслед за этим начинает возвращать некорректные значения RoundTripDelay и AdjustmentTime. Но такая ситуация иногда возникает и в процессе...
    И если datetime начинает выдавать неправильные значения, то так и продолжает. До перезапуска программы(как будто). Но иногда начинает работать как положено.
    Такой вот нестабильный глюк.
    Залез в компонент TidSNTPClient.
    Привожу часть метода datetime:
    ExpandedWrap disabled
      Begin
      Result := 0.0;
       
        SetLength(LBuffer, SizeOf(TNTPGram));
        FillBytes(LBuffer, SizeOf(TNTPGram), $00);
       
        LBuffer[0] := $1B;
        DateTimeToNTP(Now, LNTPDataGram.Xmit1, LNTPDataGram.Xmit2);
        CopyTIdUInt32(GStack.HostToNetwork(LNTPDataGram.Xmit1), LBuffer, 40);
        CopyTIdUInt32(GStack.HostToNetwork(LNTPDataGram.Xmit2), LBuffer, 44);
        //sendtime:=gettickcount;
        SendBuffer(LBuffer);
        //sendtime:=gettickcount-sendtime;
        //rectime:=gettickcount;
        ReceiveBuffer(LBuffer);
        //rectime:=gettickcount-rectime;
       
      // ...
       
      // corrected as per RFC 2030 errata
          FRoundTripDelay := (FDestinationTimestamp - FOriginateTimestamp) -
            (FTransmitTimestamp - FReceiveTimestamp);
       
          FLocalClockOffset := ((FReceiveTimestamp - FOriginateTimestamp) +
            (FTransmitTimestamp - FDestinationTimestamp)) / 2;

    Выяснил, что в случае правильной работы компонента, метод SendBuffer отрабатывает "мгновенно", а ReciveBuffer в течении 20..300 мс и фактически RoundTripDelay - это "время срабатывания" ReciveBuffer. Когда происходит глюк, вижу что ReciveBuffer начинает отрабатывать так же "мгновенно", как и SendBuffer. Ощущение, что где-то в приемном буфере остаётся мусор от предыдущего вызова ReciveBuffer и именно этот "хвост" ReciveBuffer читает. Но при этом возвращает ненулевое (и корректное) значение времени, то есть прочитанный пакет NTP проходит все проверки. :scratch:
    Uлюк происходит где-то в недрах родительского класса. Что это и как от него избавиться. :-?

    Я пока не пробовал создавать и уничтожать экземпляр TidSNTP в рантайме. Может быть это исправит ситуацию, но я хочу понять. Может, я что-то не так делаю.
      Тогда попробуйте в этот метод добавить дополнительный локальный буфер, в который скопируете значения исходные, а получение уже может сработать на сохраняемом глобальном LBuffer предварительно обнуленном.

      И еще: А ничего, что длина у этих объектов разная?
      ExpandedWrap disabled
          CopyTIdUInt32(GStack.HostToNetwork(LNTPDataGram.Xmit1), LBuffer, 40);
          CopyTIdUInt32(GStack.HostToNetwork(LNTPDataGram.Xmit2), LBuffer, 44);
        Это не размер, а индекс в буфере пакета по логике.
        Не понял про локальный буфер.
        Попробую просто обнулить буфер перед вызовом ReciveBuffer. Хотя в случае глюка тогда я скорее всего буду получать ошибку datetime.
        Сейчас попробую.

        Добавлено
        Обнуление ничего не даёт. Глюк где-то в недрах родительских классов. Точнее, даёт, глюк стал появляться чаще.
        Сообщение отредактировано: Prince -
          В локальных переменных объявите еще один SBuffer, обнулите его и используйте для отправки через SendBuffer. А для ReceiveBuffer оставьте этот LBuffer.

          Добавлено
          У меня просто нету под рукой сейчас этого класса в Lazarus. Я бы сам проверил в чем дело.
            Кажется, он вылечился. Перед вызовом datetime устанавливаю IdSNTP.Active := true, а после сбрасываю. Таким образом, сокет инициализируется при каждом вызове datetime где-то там внутри. Так вроде работает. Тогда и создание TIdSNTP в рантайме будет иметь такой же эффект, по идее.
            Увеличил таймаут по приему до 2000 мс, теперь и первый вызов отрабатывает как будто нормально. Будем посмотреть.

            Да, глюк пропал. А таймаут лучше увеличить секунд до 5.
            Сообщение отредактировано: Prince -
            0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
            0 пользователей:


            Рейтинг@Mail.ru
            [ Script execution time: 0,0253 ]   [ 16 queries used ]   [ Generated: 26.04.24, 08:28 GMT ]