TCP socket, programozás javaslataitok

Sziasztok!

Szeretnék 10 darab ip eszközről "folyamatosan" adatot olvasni egy központi feldolgozó helyen. Ezt milyen lehető legkisebb erőforrást igénylő dologgal oldanátok meg?

 

A 10 végpont adatforgalma nagyon pici. 1 ponton maximum 20 karakter információra van szükség abban a másodpercben. Mivel nincs eseményre beküldés (eszköz nem tudja), ezért a folyamatos hallgatózásra gondoltam.

Alap ötletem egy végtelen php script volt, ami minden másodpercben zárja nyitja a kapcsolatot, majd ha van adat az letárolom egy adatbázisban. Ezt erőforrás zabalásnak érzem, nem tudom mi a jobb az ilyen "stream"melésre.

Köszönöm a tanácsaitokat.

Hozzászólások

Szerkesztve: 2023. 10. 26., cs – 14:24

Én lehet elkezdeném az ismerkedést a Rust-tal és annak hálózatos részével, de úgy rémlik C-hez is az alap könyvtárak elég jó alapot adtak ilyenhez.

Vagy 20 éve kellett összekalapálnom hasonló beadandót C-ben és bár nem nagyon értettem, mégis sikerült :D

Színes vászon, színes vászon, fúj!

Kérem a Fiátot..

Szerkesztve: 2023. 10. 26., cs – 14:29

El kellene olvasni a készülék leírását, hogy hogyan lehet vele szót érteni.

Pull vagy push?

Ha push, akkor johetnek azonos idopillanatban? Ki is kell szolgalni azonnal, vagy ujra megprobalja az adatforras?

Nyitva kell tartani a kapcsolatot, vagy jobb, ha lebontod?

 

A nyelv kb mindegy, meg az AWK is jo lehet. Mondjuk sokat segitene, ha pontosan leirnad, hogy mi is a problema...

Szerkesztve: 2023. 10. 26., cs – 16:12

Melyik a klines, melyik a szerver?

Mit jelent az, hogy a lehető legkevesebb erőforrást igénylő módon oldjuk meg? Egy mikrovezérlő plusz egy Wiznet konverter elég kicsi? :-) Mert az is elbír ennyi terheléssel, ha ő lehet a kliens. Ha RPI-től felfelé lépegetünk, akkor nagyjából mindegy hogyan oldod meg, ez a kapcsolat szám és sávszélesség a mérhetőség határán lévő terhelés lesz. A megfelelő eszközökkel lehet optimális programot írni például Linuxra, de feleslegesnek tűnik.

Azzal az eszközzel csináld, amit hajlandó vagy megtanulni. Én Javában írnám, mert az a kedvencem, de annak az alap memória foglalása több MB lesz mindenképpen, az alatt nem szólal meg. Szerintem a socat program bash-ből hívogatva is működhet, ha a protokoll olyan. Kellene a leírása, ahogy NevemTeve sugallta.

A PHP szkript szerintem jó megoldás és mai mércével nem fogyaszt sokat. Annyit optimalizálnék ha muszáj egyáltalán, hogy nem adatbázisoznék, hanem simán egy fájl végéhez csapnám az új logot mindig appenddel és kész. Arra kell vigyázni, hogy egyszerre egy példány fusson, és akkor ez tökéletes megoldás.

ajjaj, megint kezdődik

1-2 éve volt már erről egy topic, de nem jutottak dűlőre

Szerkesztve: 2023. 10. 26., cs – 16:59

Szeretnék 10 darab ip eszközről "folyamatosan" adatot olvasni egy központi feldolgozó helyen.

Egy hálózaton vannak ezek a gépek? (van-e köztük tűzfal, router, proxy stb.?)

Alap ötletem egy végtelen php script volt, ami minden másodpercben zárja nyitja a kapcsolatot, majd ha van adat az letárolom egy adatbázisban. Ezt erőforrás zabalásnak érzem, nem tudom mi a jobb az ilyen "stream"melésre.

Mennyire alacsony szintre akarsz lemenni? A php-s socket eléggé magas szintű, és valóban erőforrás zabáló.

Ha egy hálózaton vannak a gépek, akkor megoldható a másodpercenkénti egyszeri lekérdezés (pull), ehhez akármit használhatsz, az overhead nem lesz számottevő. Ha azonban nem, akkor könnyen lehet, hogy csakis küldés jöhet szóba (push), hacsak nem férsz hozzá a köztes rendszerekhez és nem tudsz explicit related-allow szabályokat felkonfigurálni. Vagy esetleg egy UPnP csomag szerű üzenettel lyukat ütsz rajta, amikor bekapcsol valamelyik mérő. Mindegy, a lényeg, hogy a megoldás szempontjából fontos, egy hálózaton vannak-e.

Ezt milyen lehető legkisebb erőforrást igénylő dologgal oldanátok meg?

A lehető legkissebb erőforrás egyébként egy egyszerű UDP push (azaz a 10 berendezés másodpercenként egyszer küld egy UDP csomagot a szervernek). Ha egy hálózaton vannak, akkor nem lesz adatvesztés, nem számít, hogy nem reliable protocol (vagy ha mégis, akkor lehet, nem is fontos és nem okoz bajt, ha egy másodpercnyi frissítés kimarad, hisz a következő másodpercben úgyis jön az újabb). Egy csomagba kb 1400 bájtot tudsz belegyömöszölni (MTU - IP headers), az bőven elég neked.

Ezt piszok könnyű leprogramozni, a szerver oldalon van egy végtelen ciklusban futtatott recv, ami aztán lementegeti, amit kapott, a kliens oldalon megy másodpercenként egy send hívás és csók. Feldolgozásnál meg mindig a legutóbb lementett adatod használod (akár php-ből), így nem okoz problémát ha netán egy-egy UDP csomag mégis kiesne.

Ha a LAN hálózaton belül is előfordulhat csomagvesztés (nem túl valószínű, de ki tudja), és fontos, hogy egyetlen csomag se vesszen el, akkor érdemes elgondolkodni egy folyamatosan nyitva tartott TCP csatornán (de semmiképp sem lezárni meg újramegnyitni, az valóban iszonyatos pazarlás), vagy esetleg rádobni valami faék egyszerű reliable függvénykönyvtárat.

Javaslom nézd meg a NetQ single header libet. Mégha nem is kell a megbízhatóság, a benne lévő client.c és server.c jó példa arra, hogyan kell IPV4 / IPv6 UDP csomagokat küldeni és fogadni standard libc-vel (nézd meg pl. a my_sender() hívást a forrásban).

Küldéshez egyébként nincs is szükség programozásra / szkriptelésre, egy jól felparaméterezett netcat hívás cron-ból is elég lehet.

Egy hálózaton vannak. Adatkiesés nem baj, majd a következő másodpercben meglesz.

 

Az eszközök kérésre válaszolnak. Php-ban ezt írtam, hogy böngészőben lássam mi zajlik 1 eszközön (részlet):

$timeout = 1;
$socket2 = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_option($socket2, SOL_SOCKET, SO_RCVTIMEO, array("sec" => $timeout, "usec" => 0));
if ($socket2 === false) {
    echo 'CONN!';
    exit();
}
$result = socket_connect($socket2, $address, $service_port);
if ($result === false) {
    echo 'CONN!';
    exit();
    socket_strerror(socket_last_error($socket2)) . "\n";
}

$counter=1;

while(true) {
$buf = @socket_read($socket2, 256);
echo $buf.'----'.$counter.'.<br>';
ob_flush();
flush();
sleep(1);
$counter=$counter+1;
}
socket_shutdown($socket2, STREAM_SHUT_RDWR);

Szerintem libeventet nézd meg.

Megadhatsz neki akármennyi socketet és egy callbacket hív meg, amikor valamelyiken forgalom van.

Megszabadít egy rakás boilerplate kódtól, mégis borzasztó hatékony és platformfüggetlen is lesz az eredmény.

C vagy C++ nyelven abszolút mini binárist tudsz vele csinálni, de PHP-ból is lehet használni.

Ez esetben én arra mennék el, hogy a mérők netcat-el (vagy minimális php szkripttel socket_sendto()-t hívva) másodpercenként egyszer küldik az adatot. (Tehát push, nem pedig pull, mint a fenti példádban.)

Szerver oldalon meg egy független, CLI-ból indított, minimális php szkripttel fogadnám ezeket (itt egy példa, meg mégegy, pár sorosak csak). Amikor beesik egy csomag, akkor azzal felülírod az adott mérő legutolsó állapotát (fájlba, sql-be stb.). Hogy melyik mérőről van szó, azt berakhatod magába az üzenetbe, vagy használhatod rá a forrás ip-t.

Ettől a fogadó szkripttől függetlenül futtatod a feldolgozót (CLI-ből, webszerverből, stb. amikor kell), ami meg kizárólag ezen lementett adatokkal foglalkozik csak (nincs szükség benne hálózatkezelésre). Ez a fajta szétválasztás azért is jó, mert ha később lecseréled az UDP-t bármi másra, akkor a feldolgozóhoz nem kell nyúlni.