• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

question-closed Pobieranie danych z bazy danych - ilość prób i czas komunikacji z nie odpowiadającym hostem

Object Storage Arubacloud
0 głosów
722 wizyt
pytanie zadane 12 października 2019 w PHP przez xyz91 Nowicjusz (210 p.)
zamknięte 12 listopada 2019 przez xyz91

Cześć wszystkim, 

Problem polega na tym, że mam zadanie, w którym mam:
- rozbuduj tabelę o kolejną kolumnę, w której wyświetlaj ilość prób komunikacji z danym hostem, które pozostały bez odpowiedzi. Jeśli host zaczyna ponownie odpowiadać – to ponownie wyświetlaj w tej kolumnie cyfrę ”0”.
- rozbuduj tabelę o kolejną kolumnę, w której wyświetlaj czas, od którego nastąpiła utrata komunikacji z danym hostem. Jeśli host zaczyna ponownie odpowiadać – to ponownie wyświetlaj w tej kolumnie znak ”-”.

Kod na razie pobiera adresy z bazy danych i sprawdza czy port 80 jest OK, dorobić muszę te dwa wyżej wymienione punkty (kolejne kolumny w tabeli). Wszystko jest wyświetlane w tabeli na stronie.

Jeśli dobrze rozumuje, muszę dodać dwie kolejne kolumny w bazie mySQL i pobierać tą ilość prób oraz czas z bazy? Problemem jest napisanie kodu, ktoś mógłby pomóc?

<!DOCTYPE html>
<html>
  <head>
    <title>Page 1</title>
    <meta http-equiv="refresh" content="10" />
  </head>
 
  <body>
    <?php
     $dbhost="localhost"; $dbuser="root"; $dbpassword="xxxxxx";
     $dbname="database1";
     $conn = mysqli_connect($dbhost, $dbuser, $dbpassword, $dbname);
     if (!$conn) {
       echo "Error connection with MySQL" . PHP_EOL;
       echo "Errno: " . mysqli_connect_errno() . PHP_EOL;
       echo "Error: " . mysqli_connect_error() . PHP_EOL;
       exit;
     }
     $port = '80';
     $result = mysqli_query($conn, "SELECT * FROM addresses") or die ("Erro connection: $dbname");
     print "<TABLE CELLPADDING=10 BORDER=1>";
     print "<TR><TD>idt</TD><TD>Name</TD><TD>Working</TD><TD>Number of attempts</TD><TD>Time</TD></TR>\n";
     while ($row = mysqli_fetch_array ($result)) {
       $idt = $row[0];
       $name = $row[1];
       $host = $name;
       $fp = @fsockopen($host, $port, $errno, $errstr, 30);
       if ($fp)  
       {
         print "<TR><TD>$idt</TD><TD>$name<TD>OK</TD><TD></TD><TD></TD></TR>\n";
       }  
       else
       {
         print "<TR><TD>$idt</TD><TD>$name</TD><TD>Error</TD><TD></TD><TD></TD></TR>\n";
       }
 
     }
 
     print "</TABLE>";
     mysqli_close($conn);
   ?>
  </body>
 
</html>

 

komentarz zamknięcia: Rozwiązane!

1 odpowiedź

0 głosów
odpowiedź 12 października 2019 przez jared Gaduła (3,600 p.)

Słuchaj kolego lub koleżanko postanowiłem zmierzyć się z twoim problemem bazując na twoim rozwiązaniu, czyli styl proceduralny. Nie wiem czy przyda się ale chciałem dla siebie spróbować rozwiązać taki problem za bardzo nie zagłębiając się w tematykę socketów.

Na początku baza danych. Nie wiem jaką masz, ja bazowałem na takiej

-- utworzenie bazy danych
CREATE DATABASE database1;

-- wybranie bazy danych z ktora chcemy pracowac
USE database1;

-- utworzenie tabeli
CREATE TABLE addresses (
    idt INT NOT NULL AUTO_INCREMENT,
    name VARCHAR(15) NOT NULL,
    working BOOLEAN DEFAULT false,
    attempt_count INT DEFAULT 0,
    connection_lost_time TIME,
    PRIMARY KEY (idt)
);

-- wprowadzenie przykladowych danych
INSERT INTO addresses (name) VALUES
('127.0.0.1'),
('192.168.21.1');

Gdybyś potrzebował polecenia do zmiany istniejącej tabeli:

-- lub zmodyfikowanie istniejacej tabeli
ALTER TABLE addresses
ADD COLUMN (attempt_count INT NOT NULL DEFAULT 0)
ADD COLUMN (connection_lost_time TIME);

Twój skrypt w stylu proceduralnym. Gdybym pisał to na nowo, napewno zrobiłbym wszystko inaczej. W praktyce to co napisałem do tej pory nadaje się do poprawek. Dlaczego więc wysyłam? Dlatego, że nie mam teraz czasu na dalszą zabawę, a chciałem zaserwować podpowiedź. Daj znać co o tym sądzisz.

<?php

// 1. polaczenie z baza danych
$dbhost = '127.0.0.1';
$dbuser = 'root';
$dbpassword = '';
$dbname = 'database1';

$db_connection = mysqli_connect($dbhost, $dbuser, $dbpassword, $dbname);

if (!$db_connection) {
    die('<p style="color:red;">database connection error</p>');
}

// 1.1 dodatkowe zmienne pomocnicze
$port = 8888;
$attempt_default = 0; // domyslna wartosc, ktora nalezy wpisac, gdy host odpowiada

// 2. pobranie danych z tabeli
$result = mysqli_query($db_connection, "SELECT * FROM addresses");

// 3. wyswietlenie tabelki HTML

echo '<table style="border: 1px solid black;">';
echo '<tr><td>idt</td><td>name</td><td>working</td><td>attempt_count</td><td>time</td></tr>';

// 3.1 tworzenie wierszy w tabeli
while ($row = mysqli_fetch_array($result)) {
    $idt = $row[0];
    $name = $row[1];
    $working = $row[2];
    $attempt_count = $row[3];
    $time = $row[4];

    $workingString = $working ? 'OK' : 'BAD';
    $timeString = is_null($time) ? '-' : $time;

    $attempt_counter = $attempt_count; // licznik, ktora zlicza liczbe nieudanych prob polaczenia

    // 3.2 otwarcie polaczenia socket
    $socket_connection = fsockopen('udp://' . $name, $port, $errno, $errstr, 10);

    // 3.3 sprawdzenie czy nawiazano polaczenie socket
    // na podstawie sukcesu lub braku polaczenia nalezy wybrac: 0 lub liczbe nieudanych polaczen
    // trzeba rowniez zaktualizowac kolumne working
    if ($socket_connection) {
        echo '<p style="color:green;">Socket OK!</p>';
        $working = 1;
        $attempt_count = $attempt_default;
        $sql = sprintf('UPDATE addresses SET working = %s, attempt_count = %s WHERE idt = %s', $working, $attempt_count, $idt);
    }
    else {
        echo '<p style="color:red;">Socket Error: ' . $errno . '->' . $errstr . '!</p>';
        $working = 0;
        $attempt_counter++; // nieudane polaczenie, czyli trzeba zwiekszyc licznik
        $attempt_count = $attempt_counter; // nowa liczba prob polaczenia
        $sql = sprintf('UPDATE addresses SET working = %s, attempt_count = %s WHERE idt = %s', $working, $attempt_count, $idt);
    }

    // 3.4 wykonanie aktualizacji w tabeli z bazy danych
    // jesli zapytanie zostanie poprawnie wykonanego mozna utworzyc wiersz w tabelce HTML
    if (mysqli_query($db_connection, $sql)) {
        // 3.5 aktualizacja zmiennych na podstawie informacji o polaczeniu
        // wartosc logiczna warto zamienic na string OK lub BAD
        $workingString = $working ? 'OK' : 'BAD';
        echo '<p style="color:green;">sql update worked</p>';
    }
    else {
        echo '<p style="color:red;">sql update didnt work</p>';
    }

    // 3.6 utworzenie wiersza w tabeli HTML
    echo sprintf('<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>', $idt, $name, $workingString, $attempt_count, $timeString);

    // 3.7 jezeli zmienna wskazuje na zasob, trzeba zamknac polaczenie
    // w przeciwnym razie jezeli zmienna przechowuje wartosc bool, wiemy ze polaczenie socket nie udalo sie
    if(!is_bool($socket_connection))
    {
        fclose($socket_connection);
    }

    $socket_connection = null;
}

echo '</table>';

// 3.8 zamkniecie polaczenia z baza danych
if (mysqli_close($db_connection)) {
    echo '<p style="color:green;">closed db_connection</p>';
}

die('terminate script');

Dla osób, które będą śmiać się z kodu: jest to rozwiązanie tymczasowe i bałaganiarskie :)

komentarz 13 października 2019 przez xyz91 Nowicjusz (210 p.)
Hej,

Sprawdziłem to co zrobiłeś i prawie działa, ale jest troszkę błędów. Wolałbym jednak przełożyć to na swój kod, bo widzę, że napisałeś tak jakby od nowa innym sposobem. Da się to jakoś przełożyć na mój kod? Pomógłbyś mi, jeśli masz czas? Dzięki.
komentarz 13 października 2019 przez jared Gaduła (3,600 p.)
Napisz dokładnie treść zadania, pokaż wszystko co masz (struktura tabeli w bazie) i najlepiej opisz jeszcze dokładniej co powinno być. W wolnej chwili spróbuję coś sklecić.
komentarz 13 października 2019 przez xyz91 Nowicjusz (210 p.)

Dokładna treść zadnia jak w pierwszym poście. Wcześniejsze zadanie polegało na sprawdzeniu czy port 80 jest otwarty i wyświetleniu tego w tabeli na stronie (nie zapisuje tego w bazie danych), adresy pobiera z bazy danych np. wp.pl, fb.com, gry.ppl (tutaj specjalnie zły adres). Ten kod co wkleiłem już to robi, teraz zostały mi te dwa punkty.

Tutaj struktura tabeli: 

CREATE TABLE database1 (
    id int NOT NULL AUTO_INCREMENT,
    addresses text NOT NULL,
    count int NOT NULL,
    time int NOT NULL,
    PRIMARY KEY (id)
);

Próbowałem coś takiego zrobić, ale nie działa:

if($fp){
      print "<TR><TD>$idt</TD><TD>$name<TD>OK</TD><TD>$licznik</TD><TD></TD</TR>\n";
     $sql = "UPDATE domeny SET count = 0";
} else {
      print "<TR><TD>$idt</TD><TD>$nazwa<TD>OK</TD><TD>$licznik</TD><TD></TD</TR>\n";
       $sql = "UPDATE domeny SET count = count+1";
     }

 if (mysqli_query($polaczenie, $sql)) {
     echo "sql update";
    }
    else {
        echo "sql no update";
    }

Czas ma być liczony w sekundach od ostatniej utraty komunikacji z hostem, jeśli odpowiada ma wyświetlić "-". 

komentarz 13 października 2019 przez jared Gaduła (3,600 p.)
Nie korzystam obecnie z pc ale mogę napisać:

1. Dodaj do zapytań SQL warunek z odpowiednim ID, bo w tej chwili polecenie UPDATE zaktualizuje wszystkie wiersze w tabeli nawet gdy tylko 1 host będzie/nie będzie miał połączenia.

2. W PHP jak masz nieudane połączenie z hostem musiałbyś do bazy zapisać aktualną datę z czasem, czyli typ kolumny DATETIME lub TIMESTAMP. Powiedzmy, że połączenie nie udało się o: 2019-10-13 14:15:22. Powiedzmy, że drugi raz uruchamia się skrypt i znowu nie ma połączenia. Wtedy musiałbyś zrobić sprawdzenie aktualnej wartości z kolumny. Jeżeli jest to coś innego niż NULL, wtedy wiesz, że musisz obliczyć sekundy. Musiałbyś w PHP pobrać aktualną wartość z bazy (czyli 2019-10-13 14:15:22), przekształcić to w UNIX seconds. Następnie musiałbyś pobrać aktualny czas chyba za pomocą funkcji time() i to powinno być również w tych sekundach UNIX. Następnie odejmujesz aktualny czas od tej wartości z bazy czego wynikiem masz jak długo host nie ma połączenia. Na koniec musisz zrobić wiersz tabeli HTML i tam pokazać liczbę sekund UNIX, która wyszła z tego odejmowania.

Tak to widzę na szybko analizując. Powiem ci szczerze, że również nie jestem mocny w te klocki ale tak staralbym się rozwiązać zadanie.

Daj znać.
komentarz 13 października 2019 przez xyz91 Nowicjusz (210 p.)
edycja 13 października 2019 przez xyz91
Ilość prób udało się zrobić. Tylko nurtuje mnie jedna kwestia, muszę podawać tutaj ID tych adresów, żeby to chodziło, a jakbym chciał dodać kolejny adres np. interia.pl to ID tej strony też, muszę wpisać w kodzie. Nie da się tego jakoś inaczej zrobić, żeby nie trzeba było tego robić?

Natomiast z czasem mniej więcej wiem o co Ci chodzi, ale nie wiem jak się za to zabrać. Na razie dodałem kolumnę w bazie, która pokazuje aktualny czas. Muszę jeszcze dodać jedną kolumnę, która będzie zapisywać datę próby komunikacji? Jak to potem zapisać w kodzie?
1
komentarz 13 października 2019 przez xyz91 Nowicjusz (210 p.)
edycja 13 października 2019 przez xyz91

@jarok,

Dzięki za podpowiedzi :) Udało się zrobić, tylko nie wiem do końca czy dobrze to działa. Mógłbyś sprawdzić? :) Dodatkowo pytanie jak wcześniej, załóżmy, że dodam do tabeli kolejny adres to w kodzie będę musiał w zapytaniu do bazy danych dodać jego id, żeby to popranie działało, czy da się to jakoś napisać, żeby po prostu z automatu aktualizowało te hosty nie odpowiadające jak i te działające. Z góry dzięki :)

 

komentarz 13 października 2019 przez jared Gaduła (3,600 p.)

Zobacz mój przykład, który ci podałem dokładnie chodzi o 2 fragmenty:
 

1. fragment

// 3.1 tworzenie wierszy w tabeli
while ($row = mysqli_fetch_array($result)) {
    $idt = $row[0];

Tutaj jak widzisz do zmiennej $row pobierany jest pojedynczy wiersz z tabeli. Następnie do zmiennej $idt pobrana zostaje wartość pierwszej kolumny z tabeli, czyli wartość id danego wiersza.

 

Drugi fragment pokazuje, że możesz utworzyć łańcuch znaków, w którym podstawiasz dynamicznie wartości poszczególnych fragmentów. 

2. fragment

$sql = sprintf('UPDATE addresses SET working = %s, attempt_count = %s WHERE idt = %s', $working, $attempt_count, $idt);

Jak widzisz tworzone jest fragment WHERE idt = %s gdzie w miejsce %s będzie wstawiona wartość zmiennej $idt. Ogólnie nie musisz korzystać z funkcji sprintf, możesz to zapisać też tak:

$sql = "UPDATE nazwa_tabeli SET nazwa_kolumny = wartość_kolumny WHERE id = $id_zmienna";

ponieważ pomiędzy znakami cudzysłowiu (" ") ciąg jest przetwarzany i w miejscu wystąpienia zmiennej (czyli $id_zmienna) będzie wpisana jej wartość.

Mam nadzieję, że pomogłem :D

Dodaj do tego twojego kodu zamykanie połączenia z bazą danych oraz socket tak jak ja zrobiłem, ponieważ połączenia należy zamykać.

komentarz 13 października 2019 przez xyz91 Nowicjusz (210 p.)
Poprawiłem tak jak napisałeś i działa. Dzięki :)

Czas jest ok? Tak to miało wyglądać?

Data dodania wpisu w bazie - data ostatniej próby komunikacji = czas [s]
komentarz 13 października 2019 przez jared Gaduła (3,600 p.)

Wydaje mi się, że tak. Dla pewności dodam jeszcze mój cały kod, w którym dodałem obsługę czasu. Powinno być dobrze, można potem uprościć lub to jakoś inaczej przepisać, ale chyba nie jest tak źle.

<?php

// 1. polaczenie z baza danych
$dbhost = '127.0.0.1';
$dbuser = 'root';
$dbpassword = '';
$dbname = 'database1';

$db_connection = mysqli_connect($dbhost, $dbuser, $dbpassword, $dbname);

if (!$db_connection) {
    die('<p style="color:red;">database connection error</p>');
}

// 1.1 dodatkowe zmienne pomocnicze
$port = 8888;
$attempt_default = 0; // domyslna wartosc, ktora nalezy wpisac, gdy host odpowiada

// 2. pobranie danych z tabeli
$result = mysqli_query($db_connection, "SELECT * FROM addresses");

// 3. wyswietlenie tabelki HTML
echo '<table style="border: 1px solid black;">';
echo '<tr><td>idt</td><td>name</td><td>working</td><td>attempt_count</td><td>time</td></tr>';

// 3.1 tworzenie wierszy w tabeli
while ($row = mysqli_fetch_array($result)) {
    $idt = $row[0];
    $name = $row[1];
    $working = $row[2];
    $attempt_count = $row[3];
    $time = $row[4];

    $workingString = $working ? 'OK' : 'BAD';
    $timeString = is_null($time) ? '-' : $time;

    $attempt_counter = $attempt_count; // licznik, ktora zlicza liczbe nieudanych prob polaczenia

    // 3.2 otwarcie polaczenia socket
    $socket_connection = fsockopen('udp://' . $name, $port, $errno, $errstr, 10);

    // 3.3 sprawdzenie czy nawiazano polaczenie socket
    // na podstawie sukcesu lub braku polaczenia nalezy wybrac: 0 lub liczbe nieudanych polaczen
    // trzeba rowniez zaktualizowac kolumne working
    if ($socket_connection) {
        echo '<p style="color:green;">Socket OK!</p>';
        $working = 1;
        $attempt_count = $attempt_default;
        $sqlTime = sprintf('UPDATE addresses SET connection_lost_time = NULL WHERE idt = %s', $idt);
        $resultTime = mysqli_query($db_connection, $sqlTime);
        $timeString = '-';
    }
    else {
        echo '<p style="color:red;">Socket Error: ' . $errno . '->' . $errstr . '!</p>';
        $working = 0;
        $attempt_counter++; // nieudane polaczenie, czyli trzeba zwiekszyc licznik
        $attempt_count = $attempt_counter; // nowa liczba prob polaczenia

        // sprawdzenie czy host byl nieaktywny
        $sqlTime = sprintf('SELECT COUNT(*) FROM addresses WHERE idt = %s AND connection_lost_time IS NULL', $idt);
        $resultTime = mysqli_query($db_connection, $sqlTime);
        $resultTimeData = mysqli_fetch_array($resultTime);

        // jesli zapytanie SQL zwroci wartosc 1 (czyli istnieje wiersz) wtedy wprowadzic date
        if ($resultTimeData[0] == 1) {
            $connection_lost_time = sprintf("'%s'", date('Y-m-d H:i:s', time()));
            $sqlTime = sprintf('UPDATE addresses SET connection_lost_time = %s WHERE idt = %s', $connection_lost_time, $idt);
            $resultTime = mysqli_query($db_connection, $sqlTime);
        }
        else {
            // obliczenie liczby sekund
            // najpierw pobrac aktualny czas z bazy
            // nastepnie obliczyc roznice pomiedzy czasem teraz a tym z bazy
            // funkcja strtotime robi konwersje z formatu YYYY-mm-dd HH:mm:ss na UNIX seconds
            $sqlTime = sprintf('SELECT connection_lost_time FROM addresses WHERE idt = %s', $idt);
            $resultTime = mysqli_query($db_connection, $sqlTime);
            $resultTimeData = mysqli_fetch_array($resultTime);
            $differenceTime = time() - strtotime($resultTimeData[0]);
            $timeString = $differenceTime;
        }
    }

    // 3.4 wykonanie aktualizacji w tabeli z bazy danych
    // jesli zapytanie zostanie poprawnie wykonanego mozna utworzyc wiersz w tabelce HTML
    $sql = sprintf('UPDATE addresses SET working = %s, attempt_count = %s WHERE idt = %s', $working, $attempt_count, $idt);

    if (mysqli_query($db_connection, $sql)) {
        // 3.5 aktualizacja zmiennych na podstawie informacji o polaczeniu
        // wartosc logiczna warto zamienic na string OK lub BAD
        $workingString = $working ? 'OK' : 'BAD';
        echo '<p style="color:green;">sql update worked</p>';
    }
    else {
        echo '<p style="color:red;">sql update didnt work</p>';
    }

    // 3.6 utworzenie wiersza w tabeli HTML
    echo sprintf('<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>', $idt, $name, $workingString, $attempt_count, $timeString);

    // 3.7 jezeli zmienna wskazuje na zasob, trzeba zamknac polaczenie
    // w przeciwnym razie jezeli zmienna przechowuje wartosc bool, wiemy ze polaczenie socket nie udalo sie
    if(!is_bool($socket_connection))
    {
        fclose($socket_connection);
    }

    $socket_connection = null;
}

echo '</table>';

// 3.8 zamkniecie polaczenia z baza danych
if (mysqli_close($db_connection)) {
    echo '<p style="color:green;">closed db_connection</p>';
}

 

Podobne pytania

0 głosów
2 odpowiedzi 1,025 wizyt
0 głosów
1 odpowiedź 260 wizyt
0 głosów
3 odpowiedzi 1,198 wizyt

92,576 zapytań

141,425 odpowiedzi

319,650 komentarzy

61,961 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...