Synchronizacja czasu przez internet

0

Witam,

czy ma ktos moze jakis przyklad uzycia komponentu IdSNTP. ??

0

sciagnij demo indy (z ich strony)

0
IdSNTP.Host:= 'tempus1.gum.gov.pl';    //pobiera adres serwera
IdSNTP.Active:= true;   //łączy z serwerem
dane:=  DateTimeToStr(IdSNTP.DateTime);  //pobiera dane z serwera do zmiennej (string)
//formatowanie napisu z danych uzyskanych z serwera i wyświetlenie...
Label1.Caption:= FormatDateTime('dddd - d mmmm yyyy'+'r.' , StrToDateTime(dane));
 //jeżeli masz ustawioną opcje synchronizacji to synchronizuje...
 ifCheckSynchronizuj.Checked then IdSNTP.SyncTime; 
IdSNTP.Active:= false;   //rozłaczenie
 

Powyżej masz przykład "jednorazowy" np po kliknięciu buttona,
ale możesz to umieścić w wątku i non stop pobierać czas i synchronizować.
Tylko już nie używać IdSNTP.Active:= false;
Wystarczy raz się połączyć i pobierać dane.

0

A zna ktoś jeszcze jakieś servery o<ort>prócz</ort> 'tempus1.gum.gov.pl'?

0

polskie serwery;

praterm.com.pl
tempus1.gum.gov.pl
tempus2.gum.gov.pl
time-b.nist.gov
vega.cbk.poznan.pl

0

Odkopuję stary temat, bo nie chce zakładać nowego, a jest mniej więcej o tym samym.
Od dawna w moich aplikacjach używam komponentu TIdSNTP z Indy, który przy starcie programu pobiera datę z serwera, choćby po to żeby sprawdzić, czy data w Windowsie jest prawidłowa. Czasem jednak się zdarza, że jakiś serwer jest nie dostępny. Wtedy trzeba wybrać inny. Dotychczas zdarzało się to na tyle rzadko, że wgłębiałem się w kod, zmieniałem adres serwera NTP, kompilowałem aplikację i wgrywałem na serwer. Jest to jednak rozwiązanie raczej nieprofesjonalne, dlatego przydałby się kawałek kodu, który sprawdza dostępność danego serwera i jeśli nie ma, to łączy się z innym.
Na razie to wygląda tak:

  ShortDateFormat := 'yyyy-mm-dd hh:mm:ss';
  IdSNTP1.active := true;
  IdSNTP1.host := 'ntp.task.gda.pl';
  l_data_z_internetu.Caption := datetostr(IdSNTP1.datetime);
  IdSNTP1.active := false;
  ShortDateFormat := 'yyyy-mm-dd';
  if datetostr(IdSNTP1.datetime) <> datetostr(Date) then
    l_zla_data.Visible := true
  else
    l_zla_data.Visible := false;

Pod linią "IdSNTP1.host := 'ntp.task.gda.pl';" przydałoby się coś w stylu:

  if IdSNTP1.Connected=false then
     IdSNTP1.host := 'tempus1.gum.gov.pl';

Ale gdy to wstawiłem, to dla niego Connected zawsze było false. Jak więc mam sprawdzić dostępność serwera NTP?

0

Najpewniejszym sposobem sprawdzenia czy server jest online jest wysłanie do niego pinga. O ile wiem, to są do tego również komponenty w pakiecie Indy albo zewnętrzne moduły. Tylko spotkałem się z sytuacją, której nie potrafię rozwiązac, że jeśli używał byś swojego programu pod Wine na Linuxie lub Unixie to pingowanie po ICMP nie powiedzie się i program zachowa sie tak jakby dany host nie odpowiadał. Oczywiście polecam pingowanie po IP, a nie po nazwie hosta. Gdyż jest to szybsze sprawdzenie, nawet jak zrobisz motyw testowy jak ja i odłaczysz swój ruter od modemu, bo ja tak łączę się z Internetem od UPC. Przy okazji dodam, że lepszym nawykiem jest stosowanie gdy sprawdzamy zmienną if'em typu boolean takiego zapisu if Zmienna then jeżeli sprawdzamy czy True, a zapisu if not Zmienna then gdy sprawdzamy czy False. Tak, też kiedyś tak pisałem jak Ty powyżej, ale odradził mi to kiedyś na GG @Misiekd, więc stwierdziłem, że tak jak kiedyś w ogóle olewałem formatowanie kodu i jeszcze je celowo usuwałem, to lepiej zmienić głupie nawyki i zastosować się do rad bardziej doświadczonych programistów. Dlatego oczywiście od dawna zawsze formatuje kod gotowymi narzędziami i również od jakiegoś dłuższego czasu nie stosuje przy sprawdzaniu if'em dopisków ... = True i ... = False.

0

A kawałek kodu:

  if datetostr(IdSNTP1.datetime) <> datetostr(Date) then
    l_zla_data.Visible := true
  else
    l_zla_data.Visible := false;

chyba lepiej i czytelniej jest zastąpić jedną linią:

    l_zla_data.Visible := datetostr(IdSNTP1.datetime) <> datetostr(Date);

chociaż oczywiście to kwestia nawyków.

zaraz_zaraz napisał(a):
    l_zla_data.Visible := datetostr(IdSNTP1.datetime) <> datetostr(Date);

A tak w ogóle to po co tam jest datetostr? Jest funkcja CompareDate :)

0

To, że ping nie odpowiada nie musi oznaczać, że coś jest nie tak z połączeniem czy komputer/usługa nie działa komputer nie ma obowiązku odpowiadania na ping.
Komponent IdSNMP1 ma zdarzenie on status może tam sprawdzać stan?

0

Zrobiłem sprawdzanie dostępności serwera pingując go, choć nie wiem, jak się to będzie zachowywało, jeśli faktycznie serwer będzie niedostępny, czy np. nie wyskoczy jakiś error.

Zadeklarowałem dwie zmienne publiczne:

    hosty: TStrings;
    nr_hostu: integer;

Potem przy starcie aplikacji przypisałem im wartości:

  hosty := TStringList.Create;
  hosty.Add('ntp.task.gda.pl');
  hosty.Add('tempus1.gum.gov.pl');
  hosty.Add('tempus2.gum.gov.pl');
  hosty.Add('vega.cbk.poznan.pl');
  hosty.Add('praterm.com.pl');
  nr_hostu:=0;

A następnie to samo co wklejałem 6 dni temu:

  ShortDateFormat := 'yyyy-mm-dd hh:mm:ss';
  IdSNTP1.active := true;
  sprawdz_serwer_czasu;
  l_data_z_internetu.Caption := datetostr(IdSNTP1.datetime);
  IdSNTP1.active := false;
  ShortDateFormat := 'yyyy-mm-dd';

  if datetostr(IdSNTP1.datetime) <> datetostr(Date) then
    l_zla_data.Visible := true
  else
    l_zla_data.Visible := false;

z tym, że zamiast linii:

IdSNTP1.host := 'ntp.task.gda.pl';

wrzuciłem taką:

  sprawdz_serwer_czasu;

Jest to procedura, która wygląda tak:

procedure Tf_main.sprawdz_serwer_czasu;
var
 i: integer;
begin
  IdIcmpClient1.ReplyStatus.BytesReceived := 0;

  i:=nr_hostu;
  while IdIcmpClient1.ReplyStatus.BytesReceived = 0 do
  begin
    IdIcmpClient1.Host:=hosty[i];
    IdIcmpClient1.Ping();
    nr_hostu:=i;
    i:=i+1;
  end;

  IdSNTP1.Host:=hosty[nr_hostu];
end;

Konstruktywna krytyka mile widziana.

0

Czytasz w ogóle to, co się do Ciebie pisze? :)

  • Proponowałem zastąpić 4 linijki kodu jedną
  • istnieje funkcja CompareDate. Zamiana na string żeby porównać daty to jakiś horror.
  • jest procedura Inc(i) szybsza niż i := i + 1.

No ale walić to, Twoje palce, Twoje oczy. Za to co do kodu - sam pomyśl co się stanie jeśli ŻADEN serwer nie odpowie. Poza tym - mogę się mylić - ale odpowiedź z netu nie jest natychmiastowa, więc pomysł pingowania serwerów jeden po drugim wydaje mi się nieco naciągnięty :)

1
  • jest procedura Inc(i) szybsza niż i := i + 1.

Bardzo ciekawe.
Assembler FPC:
z -O2:
00401559 43 inc %ebx ;inc(i);
0040155A 43 inc %ebx ;i:=i+1;
z -O1:
00401558 ff0500a04200 incl 0x42a000 ;inc(i);
0040155E a100a04200 mov 0x42a000,%eax ; i:=i+1;
00401563 40 inc %eax ;j.w.
00401564 a300a04200 mov %eax,0x42a000 ;j.w.

Jeżeli to aż taki problem żeby skompilować problem pod -O2 to polecam pisać kod w assemblerze (będzie szybszy). Optymalizator od czegoś jest. Bynajmniej nie od tego żebyś czepiał się innego (równie poprawnego) zapisu tego samego który w produkcyjnym kodzie daje ten sam assembler. Zamiast bawić się w takie pierdółki polecam skorzystać z optymalizatora a samemu optymalizować istotne części kodu (w których jest to przydatne).
Ja gdy chcę mieć optymalny maszynowo kod to używam -O3 (-O4 w FPC 2.7.1) a nie zamieniam instrukcje dodawania. Też o tym pomyśl.

  • istnieje funkcja CompareDate. Zamiana na string żeby porównać daty to jakiś horror.

Uwierz mi że wiele osób tak robi, również Ty. Osobiście gdybym nie znał CompareDate to bym użył CompareByte albo innej procedury porównującej pamięć.

0

<quote="900484">Bynajmniej nie od tego żebyś czepiał się innego (równie poprawnego) zapisu;<quote>
I kto to pisze? Czołowy troll tego forum?

  • istnieje funkcja CompareDate. Zamiana na string żeby porównać daty to jakiś horror.

Uwierz mi że wiele osób tak robi, również Ty. Osobiście gdybym nie znał CompareDate to bym użył CompareByte albo innej procedury porównującej pamięć.

Wiele osób zamienia datę na string, również ja? Chyba kogoś rącza logika poniosła.. :D

0
zaraz_zaraz napisał(a):

Czytasz w ogóle to, co się do Ciebie pisze? :)

Czytam, ale póki co ważniejsze było dla mnie napisanie funkcji tak, żeby działała. Potem będę myślał nad optymalizacją. Ale dzięki za krytykę.

zaraz_zaraz napisał(a):

Za to co do kodu - sam pomyśl co się stanie jeśli ŻADEN serwer nie odpowie.

Specjalnie dodałem 5 różnych serwerów, żeby do takiej sytuacji nie doszło. Ja tą datę i tak muszę mieć, żeby móc użytkować system, więc może nawet i dobrze, jeśli aplikacja nie ruszy z powodu niedostępności serwera czasu. Powiem tak - od wielu miesięcy używałem na przemian tylko tych dwóch pierwszych serwerów i nie było sytuacji, że oba jednocześnie były niedostępne.

zaraz_zaraz napisał(a):

Poza tym - mogę się mylić - ale odpowiedź z netu nie jest natychmiastowa, więc pomysł pingowania serwerów jeden po drugim wydaje mi się nieco naciągnięty :)

Zapomniałem wkleić jeszcze tą procedurę:

procedure Tf_main.IdIcmpClient1Reply(ASender: TComponent;
  const AReplyStatus: TReplyStatus);
begin
     e_host.Text:=IdIcmpClient1.Host;
     if IdIcmpClient1.ReplyStatus.BytesReceived  = 0 then
     begin
        e_ping.Text:='Ping nie udany.';
        sleep(500);
     end
     else
     begin
        e_ping.Text:='Ping udał się w czasie '+inttostr(IdIcmpClient1.ReplyStatus.MsRoundTripTime) +' ms.';
        sleep(500);
     end;
end;

Ale powiem ci szczerze że jak "zaREMowałem" tą linijkę:

        sleep(500);

...to i tak wszystko hulało bez problemu. Pingi z tych serwerów są na poziomie kilkudziesięciu ms i wydaje mi się, że komponent IdIcmpClient ma w sobie "coś", że nie trzeba go sztucznie "usypiać" na jakiś czas. Ale to teoria "lajkonika" w temacie Indy. Póki co wszystko działa.

1

A ja tak myślę po co w ogóle ping Indy "rzuci wyjątkiem" gdy serwer nie odpowie to tak trudno obsłużyć wyjątek i ustawić wartość jakiejś zmiennej sprawdzić jej wartość i zakończyć lub nie pętle repeat until a z adresów serwerów zrobić sobie tablicę albo jakąś listę.

0
kAzek napisał(a):

A ja tak myślę po co w ogóle ping Indy "rzuci wyjątkiem" gdy serwer nie odpowie to tak trudno obsłużyć wyjątek i ustawić wartość jakiejś zmiennej sprawdzić jej wartość i zakończyć lub nie pętle repeat until a z adresów serwerów zrobić sobie tablicę albo jakąś listę.

Tak chciałem od początku zrobić - bez pingowania.
Listę serwerów mam w zmiennej TStrings.
Tylko nie bardzo wiem jak obsłużyć taki wyjątek...

procedure Tf_main.Button42Click(Sender: TObject);
var
    hosts: TStrings;
    i: integer;
    serwer_dziala: boolean;
begin
  hosts := TStringList.Create;
  hosts.Add('ntp.task.gda.pl');
  hosts.Add('tempus1.gum.gov.pl');
  hosts.Add('tempus2.gum.gov.pl');
  hosts.Add('vega.cbk.poznan.pl');
  hosts.Add('praterm.com.pl');

  serwer_dziala:=false;
  i:=0;
  repeat
    try
       IdSNTP1.Host:=hosts[i];
       l_data_z_internetu.Caption := datetostr(IdSNTP1.datetime);
       inc(i);
    finally
       serwer_dziala:=true;
    end;
  until
    serwer_dziala=true;

  IdSNTP1.active := false;
  ShortDateFormat := 'yyyy-mm-dd';
end;

Jeśli zrobię tak, jak powyżej, to wpisując zły adres serwera zatrzymuje mi się na linii:

       l_data_z_internetu.Caption := datetostr(IdSNTP1.datetime);

I teraz jeśli adres serwera jest zmyślony (np. "awenoediuhsdf.pl"), to wywala mi "Socker Error # 11001 Host not found".
Z kolei jeśli wpiszę jakiś poprawny adres serwera, ale taki, który nie jest serwerem czasu (np. "onet.pl"), to po prostu zatrzymuje mi się na tej linii i czeka w nieskończoność. Jak zrobić, żeby nie czekał w nieskończoność, tylko po jakimś czasie nie umiejąc pobrać daty, po prostu uznał "try" za nieudany?

0

IdSNTP1.ReceiveTimeout:=5000; będzie czekał 5 sec. na odp.
Co do wyjątku - znasz różnicę między finally a except? jeśli nie to Wyjątki

0
szopenfx napisał(a):

IdSNTP1.ReceiveTimeout:=5000; będzie czekał 5 sec. na odp.

Dzięki

szopenfx napisał(a):

Co do wyjątku - znasz różnicę między finally a except? jeśli nie to Wyjątki

Faktycznie pomyliłem. Teraz dobrze?

(...)
  serwer_dziala:=true;
  i:=0;
  repeat
    IdSNTP1.Host:=hosts[i];
    try
       l_data_z_internetu.Caption := datetostr(IdSNTP1.datetime);
    except
       serwer_dziala:=false;
    end;
    inc(i);
  until
     serwer_dziala=true;
(...)

Problem w tym, że po tym, jak minie te 5 sekund i nie potrafi pobrać daty, to nie przechodzi do linii w except ("serwer_dziala:=false;"), tylko pomija ją. Czyli wychodzi na to, że uznał "try" za udany. Co tym razem zrobiłem źle?

0

Wtedy serwer zwróci (a raczej nie zwróci) zero więc nie trudno sprawdzić czy IdSNTP1.datetime<> 0 a tak w ogóle pętla też powinna się kończyć gdy braknie pozycji na liście.

0

I kto to pisze? Czołowy troll tego forum?

Widać mam konkurencję.
Osobiście czepiam się gdy uważam że jakieś uproszczenie/skomplikowanie jest pojmowaniem zbyt prostym/zbyt złożonym dla danego problemu.
I nie jestem czołowym trollem tego forum, są większe trolle np. maszynaz albo Farbaniec. Tylko że ja nie wciskam kitu że trollem nie jestem.

Wiele osób zamienia datę na string, również ja? Chyba kogoś rącza logika poniosła.. :D

zaraz_zaraz napisał(a)

chyba lepiej i czytelniej jest zastąpić jedną linią:
l_zla_data.Visible := datetostr(IdSNTP1.datetime) <> datetostr(Date);
chociaż oczywiście to kwestia nawyków.

Wiem że mi wyskoczysz z blablabla że potem napisałeś inaczej. Problem leży w tym że gdybyś tak napisał raz w kodzie gdzie masz dużo do roboty to byś sobie d**y nie zawracał potem.

0
kAzek napisał(a):

Wtedy serwer zwróci (a raczej nie zwróci) zero więc nie trudno sprawdzić czy IdSNTP1.datetime<> 0 a tak w ogóle pętla też powinna się kończyć gdy braknie pozycji na liście.

No do tego już doszedłem po tym zdaniu od szopenfx:

W tej sytuacji nie sypie wyjątku (nie znam tego komponentu dobrze), ale data jest zerowana po nieudanym pobraniu

W efekcie wychodzi na to, że nie potrzeba żadnych pingów, żadnej obsługi wyjątków. My tu robimy tygodniową rozkminkę, a tymczasem do mojego kodu, jaki wkleiłem równiutko tydzień temu:

Ozi napisał(a):
  ShortDateFormat := 'yyyy-mm-dd hh:mm:ss';
  IdSNTP1.active := true;
  IdSNTP1.host := 'ntp.task.gda.pl';
  l_data_z_internetu.Caption := datetostr(IdSNTP1.datetime);
  IdSNTP1.active := false;
  ShortDateFormat := 'yyyy-mm-dd';
  if datetostr(IdSNTP1.datetime) <> datetostr(Date) then
    l_zla_data.Visible := true
  else
    l_zla_data.Visible := false;

...wystarczyło pod linią "IdSNTP1.host := 'ntp.task.gda.pl';" dodać:

  if IdSNTP1.datetime=0 then
     IdSNTP1.host := 'tempus1.gum.gov.pl';

Czyli tym samym wróciliśmy do pierwszego mojego problemu:

Ozi napisał(a):

Pod linią "IdSNTP1.host := 'ntp.task.gda.pl';" przydałoby się coś w stylu:

  if IdSNTP1.Connected=false then
     IdSNTP1.host := 'tempus1.gum.gov.pl';

Ale gdy to wstawiłem, to dla niego Connected zawsze było false. Jak więc mam sprawdzić dostępność serwera NTP?

Okazuje się, że najprościej sprawdzić dostępność serwera NTP tak: "if IdSNTP1.datetime=0 then...".
Przy czym kluczową sprawą w tym temacie była zmiana wartości IdSNTP1.ReceiveTimeout. Defaultowo miałem tam wpisane "-2" i czekał w nieskończoność na odpowiedź z serwera. Myślę, że "1000" będzie wystarczającą wartością. Jak przez sekundę serwer nie poda daty, to sprawdza w następnym.

Oczywiście powyższy kod trzeba zmienić na to, żeby nie było tylko dwóch adresów serwerów, a cała lista, która będzie na pętli kolejno sprawdzana.

Dzięki za pomoc i konstruktywną krytykę!

0
procedure Tf_main.Button42Click(Sender: TObject);
var
    hosts: TStrings;
    i: integer;
    serwer_dziala: boolean;
begin
  hosts := TStringList.Create;
  hosts.Add('onet.pl');
  hosts.Add('ntp.task.gda.pl');
  hosts.Add('tempus1.gum.gov.pl');
  hosts.Add('tempus2.gum.gov.pl');
  hosts.Add('vega.cbk.poznan.pl');
  hosts.Add('praterm.com.pl');
  serwer_dziala:=false;
  i:=0;

  ShortDateFormat := 'yyyy-mm-dd hh:mm:ss';
  IdSNTP1.active := true;
  IdSNTP1.ReceiveTimeout:=1000;

  while (serwer_dziala=false) and (i<hosts.Count) do
  begin
    IdSNTP1.Host:=hosts[i];
    if IdSNTP1.datetime<>0 then
       serwer_dziala:=true;
    inc(i);
  end;

  if IdSNTP1.datetime=0 then
     l_data_z_internetu.Caption := 'Brak dostępnych serwerów czasu. Sprawdź połączenie z internetem.'
  else
     l_data_z_internetu.Caption := datetostr(IdSNTP1.datetime);
  IdSNTP1.active := false;
  ShortDateFormat := 'yyyy-mm-dd';

I gotowe :)
Przy pierwszej próbie pobrania czasu (z onet.pl) IdSNTP1.datetime jest równe 0, więc bierze następny adres z listy.

0
-321oho napisał(a):

Widać mam konkurencję.
Osobiście czepiam się gdy uważam że jakieś uproszczenie/skomplikowanie jest pojmowaniem zbyt prostym/zbyt złożonym dla danego problemu.
I nie jestem czołowym trollem tego forum, są większe trolle np. maszynaz albo Farbaniec. Tylko że ja nie wciskam kitu że trollem nie jestem.

Czołowy - znaczy w czołówce, jak ja ostatnio siedząc na radarze za prędkość, nie "największy" :) Zresztą tamtych dwóch nie miałem okazji poznać.

zaraz_zaraz napisał(a)

Wiem że mi wyskoczysz z blablabla że potem napisałeś inaczej. Problem leży w tym że gdybyś tak napisał raz w kodzie gdzie masz dużo do roboty to byś sobie d**y nie zawracał potem.

Gdybyś nad swoją chęć czepiania się przedłożył czytanie ze zrozumieniem i całych wątków - zauważyłbyś, że "datetostr" było przeklejeniem konstrukcji Oziego przy okazji uwagi o zmieszczeniu 4 linijek w jednej. Pod spodem dodałem - nie mam możliwości edytowania postów - że lepsza jest funkcja CompareDate - i tej funkcji używam.

Dodam jeszcze gwoli prawdzie historycznej, że mit o szybszym Inc(i) powtórzyłem dość ryzykancko po jednym moim wykładowcy, który bardzo próbował mnie wdeptać w glebę przy okazji Pascala. Inne były czasy, inne kompilatory, inna optymalizacja - zapewne teraz już jest to sprawa wyłącznie estetyczna - dziękuję za naprostowanie.

0
Ozi napisał(a):

Specjalnie dodałem 5 różnych serwerów, żeby do takiej sytuacji nie doszło [...] Póki co wszystko działa.

To już praktycznie offtop, ale imo istotne :)

Fajnie, że działa, i zapewne będzie działało do us..nej śmierci (internetu) :) Problem w tym, że podobnie jak w brydżu meczowym - w programowaniu warto zabezpieczać się przed ewentualnymi wpadkami nawet tracąc jakieś drobne lewy. Jak zaczniesz programować coś co będą obsługiwać intensywnie normalni użytkownicy - prędko przekonasz się, jak bardzo potrafią być pomysłowi w bezbłędnym trafianiu na kod który "póki co działał" :)

0

Czołowy - znaczy w czołówce, jak ja ostatnio siedząc na radarze za prędkość, nie "największy" :) Zresztą tamtych dwóch nie miałem okazji poznać.

Skoro maszynaza ani Farbańca nie znaczy że nie powinieneś się wypowiadać o sprawach organizacyjnych forum bo nic nie wiesz o tym. Polecam trochę pouczyć się o historii tego forum jak i o współczesnych istotnych osobach bo z całą pewnością nikim specjalnie ważnym nie jestem. Ja tylko bryluję na peryferiach tj. w dziale Delphi i Newbie, do poziomu rozwałki wspomnianych trollów brakuje mi dużo więc nie wydaje mi się żebym zaliczał się do jakiejś specjalnej czołówki w poziomie trollingu. Maszynaz i jego rozmyślania o perpetuum mobile albo Farbaniec i jego filmiki z paleniem e-papierosów biją mnie na głowę.

Gdybyś nad swoją chęć czepiania się przedłożył czytanie ze zrozumieniem i całych wątków - zauważyłbyś, że "datetostr" było przeklejeniem konstrukcji Oziego przy okazji uwagi o zmieszczeniu 4 linijek w jednej. Pod spodem dodałem - nie mam możliwości edytowania postów - że lepsza jest funkcja CompareDate - i tej funkcji używam.

Tak, pod spodem, co znaczy że nie wpadłeś na to od razu. Najprawdopodobniej dopiero gdy się zastanowiłeś to zrozumiałeś swoją głupotę. Przy normalnym programowaniu kodziłbyś dalej nie zauważając tego. Generalnie rzecz ujmując chodziło o to że nie wpadłeś od razu na przerobienie tego na CompareDate.

0
-321oho napisał(a):

Tak, pod spodem, co znaczy że nie wpadłeś na to od razu. Najprawdopodobniej dopiero gdy się zastanowiłeś to zrozumiałeś swoją głupotę. Przy normalnym programowaniu kodziłbyś dalej nie zauważając tego. Generalnie rzecz ujmując chodziło o to że nie wpadłeś od razu na przerobienie tego na CompareDate.

Widzę, że grzeczna rozmowa straciła sens, więc może to do ciebie dotrze. Wszystkich postronnych proszę o zignorowanie tego wpisu:

Misiek, swoje dedukcje wsadź sobie w buty, będziesz wyższy, chociaż swojego ego i tak nie dościgniesz. Wytłumaczyłem jasno, jak to szło, a twoje gdybania są tyle warte ile twoja wiedza o kindersztubie. Dyskutować z koderem o minimalnej wiedzy o programowaniu - mogę, z imaginacjami prostego chama - nie podejmuję się. A o głupotę miej pretensje do swoich starszych - parę sekund wcześniej i może by cię nie było.

0

Misiek, swoje dedukcje wsadź sobie w buty, będziesz wyższy, chociaż swojego ego i tak nie dościgniesz. Wytłumaczyłem jasno, jak to szło, a twoje gdybania są tyle warte ile twoja wiedza o kindersztubie. Dyskutować z koderem o minimalnej wiedzy o programowaniu - mogę, z imaginacjami prostego chama - nie podejmuję się. A o głupotę miej pretensje do swoich starszych - parę sekund wcześniej i może by cię nie było.

Słaby hejt, gdzieś tak na poziomie gimnazjum. Jeżeli wydawało ci się że takim błotkiem mnie trafisz, to się myliłeś. Ale widzę że o ile wytłumaczyć tobie się nie udało, to udało się ztrollować :) . Miło było.

Widzę, że grzeczna rozmowa straciła sens, więc może to do ciebie dotrze.

Straciła sens gdyż pokazałem ci jak to widzę a ciebie to nie zadowala? Super :) .

0
zaraz_zaraz napisał(a):
Ozi napisał(a):

Specjalnie dodałem 5 różnych serwerów, żeby do takiej sytuacji nie doszło [...] Póki co wszystko działa.

To już praktycznie offtop, ale imo istotne :)

Fajnie, że działa, i zapewne będzie działało do us..nej śmierci (internetu) :) Problem w tym, że podobnie jak w brydżu meczowym - w programowaniu warto zabezpieczać się przed ewentualnymi wpadkami nawet tracąc jakieś drobne lewy. Jak zaczniesz programować coś co będą obsługiwać intensywnie normalni użytkownicy - prędko przekonasz się, jak bardzo potrafią być pomysłowi w bezbłędnym trafianiu na kod który "póki co działał" :)

Wiem i dlatego, jakbyś zwrócił uwagę, to najpierw:

Ozi napisał(a):

póki co ważniejsze było dla mnie napisanie funkcji tak, żeby działała. Potem będę myślał nad optymalizacją.

a potem:

Ozi napisał(a):
(...)
  while (serwer_dziala=false) and (i<hosts.Count) do
(...)
  if IdSNTP1.datetime=0 then
     l_data_z_internetu.Caption := 'Brak dostępnych serwerów czasu. Sprawdź połączenie z internetem.'
  else
     l_data_z_internetu.Caption := datetostr(IdSNTP1.datetime);

Tak więc napisałem, że "zabezpieczę się" później i to zrobiłem :)

CompareDate też już użyłem:

  if CompareDate(IdSNTP1.datetime, Date) <> 1  then
    l_zla_data.Visible := true
  else
    l_zla_data.Visible := false;

Co do tego:

zaraz_zaraz napisał(a):

A kawałek kodu:

  if datetostr(IdSNTP1.datetime) <> datetostr(Date) then
    l_zla_data.Visible := true
  else
    l_zla_data.Visible := false;

chyba lepiej i czytelniej jest zastąpić jedną linią:

    l_zla_data.Visible := datetostr(IdSNTP1.datetime) <> datetostr(Date);

chociaż oczywiście to kwestia nawyków.

...to akurat dla mnie czytelniej to jest w 4 linijkach. Może mniej optymalnie, ale czytelniej.

Dzięki za pomoc i przestańcie się już kłócić - temat mi rozmywacie ;)

0

tak

0

To ja dodam jeszcze, że timeout ustawiony na 1 sekundę to mało. Można odpalić kilka wątków, jeden na każdy serwer, timeout dać na jakieś 30 sekund, a gdy odpowie pierwszy serwer to ubić resztę wątków.

1 użytkowników online, w tym zalogowanych: 0, gości: 1