Byl vydán Mozilla Firefox 126.0. Přehled novinek v poznámkách k vydání, poznámkách k vydání pro firmy a na stránce věnované vývojářům. Vylepšena byla funkce "Zkopírovat odkaz bez sledovacích prvků". Přidána byla podpora zstd (Zstandard). Řešeny jsou rovněž bezpečnostní chyby. Nový Firefox 126 je již k dispozici také na Flathubu a Snapcraftu.
Grafana (Wikipedie), tj. open source nástroj pro vizualizaci různých metrik a s ní související dotazování, upozorňování a lepší porozumění, byla vydána ve verzi 11.0. Přehled novinek v aktualizované dokumentaci.
Byla vydána nová verze 24.0 linuxové distribuce Manjaro (Wikipedie). Její kódové jméno je Wynsdey. Ke stažení je v edicích GNOME, KDE PLASMA a XFCE.
Byla představena oficiální rozšiřující deska Raspberry Pi M.2 HAT+ pro připojování M.2 periferii jako jsou NVMe disky a AI akcelerátory k Raspberry Pi 5. Cena je 12 dolarů.
V Praze o víkendu proběhla bastlířská událost roku - výstava Maker Fair v Praze. I strahovští bastlíři nelenili a bastly ostatních prozkoumali. Přijďte si proto i vy na Virtuální Bastlírnu popovídat, co Vás nejvíce zaujalo a jaké projekty jste si přinesli! Samozřejmě, nejen českou bastlířskou scénou je člověk živ - takže co se stalo ve světě a o čem mohou strahováci něco říct? Smutnou zprávou může být to, že provozovatel Sigfoxu jde do
… více »Kam asi vede IllllIllIIl.llIlI.lI? Zkracovač URL llIlI.lI.
Společnost OpenAI představila svůj nejnovější AI model GPT-4o (o jako omni, tj. vše). Nově také "vidí" a "slyší". Videoukázky na 𝕏 nebo YouTube.
Ondřej Filip publikoval reportáž z ceremonie podpisu kořenové zóny DNS. Zhlédnout lze také jeho nedávnou přednášku Jak se podepisuje kořenová zóna Internetu v rámci cyklu Fyzikální čtvrtky FEL ČVUT.
Společnost BenQ uvádí na trh novou řadu monitorů RD určenou pro programátory. První z nich je RD240Q.
Byl aktualizován seznam 500 nejvýkonnějších superpočítačů na světě TOP500. Nejvýkonnějším superpočítačem nadále zůstává Frontier od HPE (Cray) s výkonem 1,206 exaFLOPS. Druhá Aurora má oproti loňsku přibližně dvojnásobný počet jader a dvojnásobný výkon: 1,012 exaFLOPS. Novým počítačem v první desítce je na 6. místě Alps. Novým českým počítačem v TOP500 je na 112. místě C24 ve Škoda Auto v Mladé Boleslavi. Ostravská Karolina, GPU
… více »UDP je zkratka angl. User Datagram Protocol a je to základní internetový protokol. Na rozdíl od minule popisovaného TCP se hodí spíš tam, kde se počítá se ztrátami paketů, přičemž není žádoucí odesílat je znova (hry, VoIP, internetová rádia). UDP totiž nezaručuje, že se odeslaná data dostanou ke svému cíli – když to nevyjde napoprvé, tak se to znova nezkouší. Nezaručuje ani pořadí, ve kterém data přijdou. Někdy se používá pro jednoduchost (DNS). Výhodou oproti TCP je nižší režie. Někdo volí UDP také kvůli vyšší flexibilitě, například když si chce kontrolu doručení naprogramovat sám nějakým velmi specifickým způsobem.
S UDP sockety se v Qt pracuje přes objekt QUdpSocket. Přes tento objekt posíláme datagramy metodou writeDatagram(), které zadáme data a adresu+port, kam je chceme poslat. Zrovna tak můžeme datagramy číst, tzn. použít socket jako server. Nejdřív je nutné socket spojit s nějakou adresou a portem pomocí metody bind() a potom lze přečíst datagram z fronty metodou readDatagram().
Jelikož je práce se sockety v Qt docela jednoduchá a navíc práce s UDP se (až na specifické věci) podobá práci s TCP (viz díl o TCP), rozhodl jsem se udělat příklad velice prostý. Klient posílá datagramy a server je přijímá a vypisuje na standardní výstup. Oba programy jsou jako obvykle v angličtině, protože nesnesu češtinu v kódu, ale dodávám k nim českou lokalizaci.
Server poslouchá (napevno) na localhostu na portu 2266, tzn. 127.0.0.1:2266. Pouze čeká na příchozí datagramy a jakmile mu nějaký přijde, vypíše jeho adresáta a příchozí data. Když někdo na server pošle datagram, řekněme text „Hello World!“, tak se vypíše něco jako:
91.121.174.105:2266 říká: Hello World!
udpserver.h
: API.
#ifndef UDPSERVER_H #define UDPSERVER_H #include <QObject> #include <QAbstractSocket> #include <QTextStream> class QUdpSocket; class UdpServer : public QObject { Q_OBJECT public: UdpServer(); private: QUdpSocket* socket; QTextStream out; private slots: void readDatagrams(); void handleError(); }; #endif // UDPSERVER_H
udpserver.cpp
: Spolehlivé čtení datagramů se řeší zajímavým způsobem. Prohlédněte si slot readDatagrams()
. Pro čekající datagram vytvoří proměnnou typu QByteArray na data (str
), nastaví velikost tohoto pole bajtů (lze zjistit metodou socketu pendingDatagramSize()
) a poté předá pomocí str.data()
ukazatel char*
metodě socketu readDiagram()
. Přes tento ukazatel se data z datagramu přímo zapíšou do instance QByteArray, pod kterou ukazatel patří (tzn. do str
).
#include "udpserver.h" #include <QtNetwork> UdpServer::UdpServer() : out(stdout, QIODevice::WriteOnly) { // vytvoříme UDP socket socket = new QUdpSocket(this); // připojíme slot pro zpracování datagramu connect(socket, SIGNAL(readyRead()), SLOT(readDatagrams())); // a slot pro zpracování chyb connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(handleError())); // pokusíme se spustit UDP server if(socket->bind(QHostAddress::Any, 2266)) { // spuštěno out << tr("socket bound to port 2266 on all available interfaces") << endl; } else { // nelze spustit // touto oblezličkou zajistíme ukončení programu (po vykonání konstruktoru) QTimer::singleShot(0, qApp, SLOT(quit())); out << tr("couldn't bind socket to port 2266") << endl; } } // zpracovává chybu void UdpServer::handleError() { // vypíše chybovou hlášku out << "error: " << socket->errorString() << endl; } // přečte čekající UDP datagram(y) void UdpServer::readDatagrams() { // dokud jsou ve frontě nepřečtené datagramy while(socket->hasPendingDatagrams()) { // vytvoříme si pro datagram: // pole bajtů (řetězec) QByteArray str; // adresu QHostAddress addr; // a port (unsigned short) quint16 port; // nastavíme poli správnou velikost str.resize(socket->pendingDatagramSize()); // načteme data z datagramu socket->readDatagram(str.data(), str.size(), &addr, &port); out << addr.toString() << ":" << port << " " << tr("says") << ": " << str << endl; } }
main.cpp
: Nastavíme UTF-8 pro C řetězce a lokalizaci. Načteme soubor s překladem.
#include <QCoreApplication> #include <QLocale> #include <QTextCodec> #include <QTranslator> #include "udpserver.h" int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); { QTextCodec* unicode = QTextCodec::codecForName("UTF-8"); QTextCodec::setCodecForCStrings(unicode); QTextCodec::setCodecForTr(unicode); } QTranslator t; t.load("udpserver_" + QLocale::system().name()); a.installTranslator(&t); UdpServer s; return a.exec(); }
Zdrojáky si můžete stáhnout v archívu udpserver.tar.bz2.
Klient má jednoduchou příkazovou řádku umožňující čtyři operace: vypsat nápovědu, nastavit (či vypsat nastavenou) adresu, nastavit (či vypsat nastavený) port a odeslat UTF-8 řetězec na nastavenou adresu a port (výchozí je 127.0.0.1:2266). Pokud chcete UDP server vyzkoušet ze vzdáleného serveru, na kterém není nainstalované Qt, můžete jako klienta použít netcat
v UDP režimu (-u).
Práce s programem vypadá takto:
$ ./udpclient potřebujete-li pomoc, napište "help" a zmáčkněte enter > help help Vypíše tuto nápovědu host [IP] Nastaví adresu na danou hodnotu port [port] Nastaví port na danou hodnotu send [text] Pošle datagram > host hostitel je nastaven na 127.0.0.1 > host 255.255.255.255 adresa hostitele byla nastavena na 255.255.255.255 > host hostitel je nastaven na 255.255.255.255 > port port je nastaven na 2266 > send Hello World! odesílám diagram s textem "Hello World!" na 255.255.255.255:2266 > ^C
udpclient.h
: API.
#ifndef UDPCLIENT_H #define UDPCLIENT_H #include <QObject> #include <QHostAddress> #include <QTextStream> class QUdpSocket; class UdpClient : public QObject { Q_OBJECT public: UdpClient(); private: QUdpSocket* socket; QTextStream out; QHostAddress addr; quint16 port; void commandLine(); void processCommand(const QString& command); void sendDatagram(); private slots: void handleError(); }; #endif // UDPCLIENT_H
udpclient.cpp
#include "udpclient.h" #include <QTextStream> #include <QtNetwork> #include <cstdio> UdpClient::UdpClient() : // nastavíme pro výpis na std. výstup out(stdout, QIODevice::WriteOnly), // výchozí adresa je 127.0.0.1:2266 addr(QHostAddress::LocalHost), port(2266) { // vytvoříme UDP socket socket = new QUdpSocket(this); // připojíme k němu slot pro zpracování chyb connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(handleError())); this->commandLine(); } // vypíše chybu void UdpClient::handleError() { out << tr("socket error:") << " " << socket->errorString() << endl; } // zpracuje příkaz void UdpClient::processCommand(const QString& command) { // příkaz QString cmd = command.section(' ', 0, 0); // a jeho argumenty QString str = ""; //qDebug() << "command:" << command << "cmd:" << cmd; // pokud je příkaz prázdný, nastavíme výchozí (help) if(cmd.isEmpty()) cmd = "help"; else // jinak si uložíme argumenty příkazu str = command.mid(cmd.size()+1); if(cmd == "host") { if(str.isEmpty()) { // pokud nemá argumenty, vypíšeme aktuální adresu out << tr("host is set to %1").arg(addr.toString()) << endl; return; } // uložíme aktuální adresu QHostAddress prevAddr(addr); // nastavíme novou adresu if(addr.setAddress(str)) { out << tr("host address has been set to %1") .arg(addr.toString()) << endl; } else { // a když to selže (nesprávný formát adresy), nastavíme zpátky tu předchozí out << tr("couldn't set the given host address: %1" .arg(str) << endl; addr = prevAddr; } } else if(cmd == "port") { if(str.isEmpty()) { // pokud nemá argumenty, vypíšeme aktuální port out << tr("port is set to %1").arg(port) << endl; return; } // kontrola konverze stringu na integer bool ok; // převedeme argument na int int p = str.toInt(&ok); // pokud byla konverze úspěšná a port je v rozsahu, nastavíme jej // jako aktuální if(ok && p >= 0 && p < 65536) { port = (quint16) p; out << tr("port has been set to %1").arg(port) << endl; } else { out << tr("couldn't set port to %1").arg(str) << endl; } } else if(cmd == "send") { // pokud byl zadán argument, odešleme datagram if(str.isEmpty()) { out << tr("nothing to send, aborting") << endl; } else { out << tr("sending datagram with text \"%1\" to %2:%3") .arg(str).arg(addr.toString()).arg(port) << endl; socket->writeDatagram(str.toUtf8(), addr, port); } } else { // pokud byl zadán neplatný příkaz, informujeme o tom if(cmd != "help") out << tr("error: unknown command: %1").arg(cmd) << endl; // vypíšeme nápovědu out << "help\t\t\t" << tr("Prints this help") << "\nhost [IP]\t\t" << tr("Sets the address to a given value") << "\nport [port]\t\t" << tr("Sets the port to a given value") << "\nsend [text]\t\t" << tr("Sends a datagram") << endl; } } void UdpClient::commandLine() { out << tr("if you need help, type `help' and hit return") << endl; // objekt pro čtení ze std. vstupu QTextStream in(stdin, QIODevice::ReadOnly); // řetězec, do kterého budeme ukládat std. vstup QString input; // hlavní smyčka forever // klíčové slovo Qt, totéž jako for(;;) { // vypíšeme prompt out << "> "; out.flush(); // načteme řádek ze std. vstupu input = in.readLine(512+5); // zpracujeme načtený řádek (příkaz) this->processCommand(input); } }
main.cpp
#include <QCoreApplication> #include <QLocale> #include <QTextCodec> #include <QTranslator> #include "udpclient.h" int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); { QTextCodec* unicode = QTextCodec::codecForName("UTF-8"); QTextCodec::setCodecForCStrings(unicode); QTextCodec::setCodecForTr(unicode); } QTranslator t; t.load("udpclient_" + QLocale::system().name()); a.installTranslator(&t); UdpClient main; return a.exec(); }
Zdrojáky si můžete stáhnout v archívu udpclient.tar.bz2.
Nástroje: Tisk bez diskuse
Tiskni Sdílej:
Pouze čeká na příchozí datagramy a jakmile mu nějaký přijde, vypíše jeho adresáta a příchozí data....vypíše jeho odesílatele...
Mám dotaz trochu off topic: Je to nějaká nová fíčura Abíčka, že se mi rozbalovací boxy se zdrojáky nahrazují plně rozbaleným textem? Prý nejaký JavaScript code syntax highlighter Alexe Gorbatcheva, viz. přiložený obrázek...
Předchozí díly tohoto seriálu to nedělají a v mém profilu jsem vypinač nenašel.