abclinuxu.cz AbcLinuxu.cz itbiz.cz ITBiz.cz HDmag.cz HDmag.cz abcprace.cz AbcPráce.cz
AbcLinuxu hledá autory!
Inzerujte na AbcPráce.cz od 950 Kč
Rozšířené hledání
×
    dnes 13:33 | Nová verze

    Byla vydána nová verze 6.18 živé linuxové distribuce Tails (The Amnesic Incognito Live System), jež klade důraz na ochranu soukromí uživatelů a anonymitu. Nově se lze k síti Tor připojit pomocí mostu WebTunnel. Tor Browser byl povýšen na verzi 14.5.5. Thunderbird na verzi 128.12.0. Další změny v příslušném seznamu.

    Ladislav Hagara | Komentářů: 0
    včera 14:33 | IT novinky

    Meta představila prototyp náramku, který snímá elektrickou aktivity svalů (povrchová elektromyografie, EMG) a umožňuje jemnými gesty ruky a prstů ovládat počítač nebo různá zařízení. Získané datové sady emg2qwerty a emg2pose jsou open source.

    Ladislav Hagara | Komentářů: 0
    včera 14:22 | Nová verze

    Byla vydána (𝕏) nová verze 25.7 open source firewallové a routovací platformy OPNsense (Wikipedie). Jedná se o fork pfSense postavený na FreeBSD. Kódový název OPNsense 25.7 je Visionary Viper. Přehled novinek v příspěvku na fóru.

    Ladislav Hagara | Komentářů: 0
    včera 13:33 | IT novinky

    Před 40 lety, 23. července 1985, společnost Commodore představila první počítač Amiga. Jednalo se o počítač "Amiga od Commodore", jenž byl později pojmenován Amiga 1000. Mělo se jednat o přímou konkurenci počítače Apple Macintosh uvedeného na trh v lednu 1984.

    Ladislav Hagara | Komentářů: 2
    včera 06:00 | IT novinky

    T‑Mobile USA ve spolupráci se Starlinkem spustil službu T-Satellite. Uživatelé služby mohou v odlehlých oblastech bez mobilního signálu aktuálně využívat satelitní síť s více než 650 satelity pro posílání a příjem zpráv, sdílení polohy, posílání zpráv na 911 a příjem upozornění, posílání obrázků a krátkých hlasových zpráv pomocí aplikace Zprávy Google. V plánu jsou také satelitní data.

    Ladislav Hagara | Komentářů: 9
    23.7. 21:55 | Komunita

    Společnost Proxmox Server Solutions stojící za virtualizační platformou Proxmox Virtual Environment věnovala 10 000 eur nadaci The Perl and Raku Foundation (TPRF).

    Ladislav Hagara | Komentářů: 2
    23.7. 21:22 | Bezpečnostní upozornění

    Byla vydána nová verze 2.4.65 svobodného multiplatformního webového serveru Apache (httpd). Řešena je bezpečnostní chyba CVE-2025-54090.

    Ladislav Hagara | Komentářů: 0
    23.7. 14:22 | IT novinky

    Společnost Proton AG stojící za Proton Mailem a dalšími službami přidala do svého portfolia AI asistenta Lumo.

    Ladislav Hagara | Komentářů: 7
    23.7. 12:22 | IT novinky

    Amazon koupil společnost Bee zaměřenou na nositelnou osobní AI aktuálně nabízející náramek Pioneer (YouTube) s mikrofony zaznamenávající vše kolem [𝕏, LinkedIn].

    Ladislav Hagara | Komentářů: 6
    23.7. 04:33 | IT novinky

    Společnost Teufel nedávno představila svůj první open source Bluetooth reproduktor MYND.

    Ladislav Hagara | Komentářů: 13
    Kolik tabů máte standardně otevřeno ve web prohlížeči?
     (28%)
     (25%)
     (6%)
     (5%)
     (5%)
     (2%)
     (2%)
     (28%)
    Celkem 123 hlasů
     Komentářů: 15, poslední včera 15:10
    Rozcestník

    Konzolové programy v Qt 4 – 2 (práce s HTTP a FTP)

    1. 9. 2009 | David Watzke | Programování | 4325×

    V dnešním díle se budu věnovat modulu QtNetwork, konkrétně si ukážeme nějaké základy práce s protokoly HTTP a FTP.

    Obsah

    Úvod do síťování v Qt

    link

    Práci s protokoly HTTP a FTP implementují třídy QHttpQFtp, které jsou v Qt dostupné už mnoho let. Ve verzi 4.4 se objevila třída QNetworkAccessManager, která poskytuje jednodušší, ale přesto mocnější API a vývojáři doporučují její použití v nových programech.

    Síťování je asynchronní a využívá technologie signálů a slotů. Pošlete požadavek, vytvoří se objekt s odpovědí a tento objekt potom vyšle signál, když je požadavek vyřízený nebo když dojde k chybě.

    Při vytváření projektů pracujících s modulem QtNetwork v Qt Creatoru si nezapomeňte modul vyžádat. Pokud projekt vytváříte ručně, tak si do .pro souboru přidejte řádek QT += network.

    HTTP hlavičky

    link

    Ukážeme si, jak poslat HTTP požadavek GET a vypsat získané hlavičky. Program funguje takto:

    $ ./httphead http://www.abclinuxu.cz/
    Expires: Fri, 22 Dec 2000 05:00:00 GMT
    Set-Cookie: JSESSIONID=5117noj9m1ik;Path=/
    Content-Type: text/html; charset=utf-8
    Last-Modified: Thu, 27 Aug 2009 13:38:35 GMT
    Cache-Control: no-cache, must-revalidate
    Pragma: no-cache
    Content-Encoding: gzip
    Server: Jetty(6.1.11)

    http.h: API.

    #ifndef HTTP_H
    #define HTTP_H
    
    #include <QObject>
    #include <QNetworkReply>
    #include <QTextStream>
    
    class QNetworkAccessManager;
    
    class HTTP : public QObject
    {
    	Q_OBJECT
    public:
    	HTTP();
    	int run();
    
    private:
    	QNetworkAccessManager *manager;
    	// objekt pro zápis na std. výstup
    	QTextStream cout;
    
    private slots:
    	void gotReply(QNetworkReply* reply);
    	void gotError(QNetworkReply::NetworkError);
    };
    
    #endif // HTTP_H
    

    http.cpp

    #include "http.h"
    
    /*
    #include <QCoreApplication>
    #include <QNetworkAccessManager>
    #include <QNetworkRequest>
    #include <QStringList>
    */
    
    // includne celý modul QtNetwork, který s sebou vtáhne QtCore
    #include <QtNetwork>
    // tohle potřebujeme pro stdout
    #include <cstdio>
    
    HTTP::HTTP() : cout(stdout, QIODevice::WriteOnly)
    {
    	manager = new QNetworkAccessManager(this);
    
    	// spojíme signál značící vyřízení požadavku se slotem,
    	// který zpracuje odpověď
    	connect(manager, SIGNAL(finished(QNetworkReply*)),
    		this, SLOT(gotReply(QNetworkReply*)));
    }
    
    int HTTP::run()
    {
    	// zkontrolujeme počet argumentů, případně vypíšeme nápovědu
    	QStringList args = qApp->arguments();
    	if(args.size() != 2)
    	{
    		cout << "usage: " << args.at(0) << " [http url]\n";
    		cout.flush();
    		// odsud nelze ukončit program běžným způsobem,
    		// vysvětlení najdete u souboru main.cpp
    		return 1;
    	}
    
    	QString url = args.at(1);
    	// pošleme HTTP požadavek HEAD na dané URL, uložíme si ukazatel na odpověď
    	QNetworkReply* reply = manager->head(QNetworkRequest(QUrl(url)));
    	// spojíme odpověď se slotem, který zpracuje případnou chybu
    	connect(reply, SIGNAL(error(QNetworkReply::NetworkError)),
    		this, SLOT(gotError(QNetworkReply::NetworkError)));
    
    	return 0;
    }
    
    // vypíše všechny hlavičky a ukončí program
    void HTTP::gotReply(QNetworkReply* reply)
    {
    	foreach(QByteArray header, reply->rawHeaderList())
    	{
    		QByteArray value = reply->rawHeader(header);
    		cout << header << ": " << value << "\n";
    	}
    	cout.flush();
    	qApp->exit(0);
    }
    
    // vypíše chybu a ukončí program
    void HTTP::gotError(QNetworkReply::NetworkError e)
    {
    	switch(e)
    	{
    	case QNetworkReply::NoError:
    		break;
    	case QNetworkReply::ConnectionRefusedError:
    		cout << tr("connection refused") << "\n";
    		break;
    	case QNetworkReply::RemoteHostClosedError:
    		cout << tr("the remote server closed the connection") << "\n";
    		break;
    	case QNetworkReply::HostNotFoundError:
    		cout << tr("host not found") << "\n";
    		break;
    	case QNetworkReply::TimeoutError:
    		cout << tr("connection timed out") << "\n";
    		break;)
    	case QNetworkReply::ProtocolUnknownError:
    		cout << tr("unknown protocol (did you forget http:// ?)") << "\n";
    		break;
    	default:
    		cout << tr("an error occured") << "\n";
    		break;
    	}
    	cout.flush();
    	qApp->exit(2);
    }
    

    main.cpp: V metodě run() nelze ukončit program klasickým způsobem, protože ještě neběží smyčka událostí. Jelikož zde program ukončit potřebujeme (pokud uživatel nezadá argument – URL), tak jsem zvolil jedno z mnoha řešení, jak to obejít.

    #include <QCoreApplication>
    
    #include "http.h"
    
    int main(int argc, char *argv[])
    {
    	QCoreApplication a(argc, argv);
    
    	HTTP main;
    	if(main.run() != 0)
    		return 1;
    
    	return a.exec();
    }
    

    Zdrojáky si můžete stáhnout v archívu httphead.tar.bz2.

    Stahování souborů

    link

    Jelikož má QNetworkAccessManager takové pěkné rozhraní pro stahování souborů, rozhodl jsem se předvést zde metodu get() právě pro stahování z FTP.

    Výstup programu vypadá následovně:

    $ ./ftpget ftp://gentoo.mirror.web4u.cz/releases/amd64/autobuilds/20090716/install-amd64-minimal-20090716.iso
    downloaded 121188352 bytes (out of 121188352), which is 100%
    download finished, file saved as install-amd64-minimal-20090716.iso
    
    $ ./ftpget http://gentoo.mirror.web4u.cz/snapshots/portage-20090818.tar.bz2
    downloaded 36430733 bytes (out of 36430733), which is 100%
    download finished, file saved as portage-20090818.tar.bz2

    ftpget.h: API.

    #ifndef FTPGET_H
    #define FTPGET_H
    
    #include <QObject>
    #include <QTextStream>
    #include <QNetworkReply>
    
    class QFile;
    class QNetworkAccessManager;
    
    class FtpGet : public QObject
    {
    	Q_OBJECT
    public:
    	FtpGet();
    	int run();
    
    private:
    	QFile* file;
    	QString fileName;
    	QNetworkAccessManager* manager;
    	QNetworkReply* reply;
    	QTextStream cout;
    
    private slots:
    	void downloadFinished(QNetworkReply*);
    	void showProgress(qint64, qint64);
    	void writeData();
    	void handleError(QNetworkReply::NetworkError);
    };
    
    #endif // FTPGET_H
    

    ftpget.cpp:

    #include "ftpget.h"
    
    #include <QtNetwork>
    
    FtpGet::FtpGet() : cout(stdout, QIODevice::WriteOnly)
    {
    	manager = new QNetworkAccessManager(this);
    
    	connect(manager, SIGNAL(finished(QNetworkReply*)),
    		this, SLOT(downloadFinished(QNetworkReply*)));
    }
    
    int FtpGet::run()
    {
    	// zkontrolujeme počet argumentů, případně vypíšeme nápovědu
    	QStringList args = qApp->arguments();
    	if(args.size() != 2)
    	{
    		cout << "usage: " << args.at(0) << " [ftp://file]\n";
    		cout.flush();
    		return 1;
    	}
    
    	QUrl url(args.at(1));
    
    	// získáme z URL název souboru
    	fileName = url.path().split('/').last();
    	if(fileName.isEmpty())
    		fileName = QString("file_from_%1").arg(url.host());
    
    	// otevřeme soubor pro zápis
    	file = new QFile(fileName);
    	if(!file->open(QIODevice::WriteOnly))
    	{
    		cout << "could not open the file (" << fileName << ")\n";
    		cout.flush();
    		return 1;
    	}
    
    	// začneme stahovat
    	reply = manager->get(QNetworkRequest(url));
    
    	// propojíme signály s funkcemi pro zápis, výpis průběhu a zpracování chyb
    	connect(reply, SIGNAL(downloadProgress(qint64,qint64)),
    		this, SLOT(showProgress(qint64,qint64)));
    	connect(reply, SIGNAL(error(QNetworkReply::NetworkError)),
    		this, SLOT(handleError(QNetworkReply::NetworkError)));
    	connect(reply, SIGNAL(readyRead()), this, SLOT(writeData()));
    
    	return 0;
    }
    
    // zapíše průběžně stažená data
    void FtpGet::writeData()
    {
    	file->write(reply->readAll());
    }
    
    // zavře soubor, informuje o dokončení stahování a ukončí program
    void FtpGet::downloadFinished(QNetworkReply* reply)
    {
    	Q_UNUSED( reply )
    
    	if(file && file->isOpen())
    		file->close();
    	cout << QString("\ndownload finished, file saved as %1\n").arg(fileName);
    	cout.flush();
    	qApp->quit();
    }
    
    // vypíše průběh stahování
    void FtpGet::showProgress(qint64 dl, qint64 all)
    {
    	// procenta
    	int perc = 0;
    
    	// spočítá kolik procent je staženo (pokud to lze)
    	if(dl > 0 && all > 0)
    		perc = dl / (all / 100);
    
    	// pomocný řetězec s celkovou velikostí
    	QString sizestr = (all == -1) ? "[unknown total size]" : QString::number(all);
    
    	// pomocný řetězec s procenty
    	QString percstr = "";
    	if (perc != 0)
    		percstr = QString(", which is %1%").arg(perc);
    
    	// vypíše info o průběhu stahování
    	cout << QString("\rdownloaded %1 bytes (out of %2)").arg(dl).arg(sizestr) << percstr << "\t\t";
    }
    
    // zpracuje chybu (v tomto případě jen vypíše chybový kód, viz první program pro úplné řešení)
    void FtpGet::handleError(QNetworkReply::NetworkError e)
    {
    	cout << "\nan error ocurred (code #" << e << "), see http://qt.nokia.com/doc/qnetworkreply.html#NetworkError-enum\n";
    	qApp->exit(2);
    }
    

    main.cpp:

    #include <QCoreApplication>
    
    #include "ftpget.h"
    
    int main(int argc, char *argv[])
    {
    	QCoreApplication a(argc, argv);
    
    	FtpGet main;
    	if(main.run() != 0)
    		return 1;
    
    	return a.exec();
    }
    

    Zdrojáky si můžete stáhnout v archívu ftpget.tar.bz2.

           

    Hodnocení: 100 %

            špatnédobré        

    Nástroje: Tisk bez diskuse

    Tiskni Sdílej: Linkuj Jaggni to Vybrali.sme.sk Google Del.icio.us Facebook

    Komentáře

    Vložit další komentář

    1.9.2009 00:25 sharpiq
    Rozbalit Rozbalit vše Re: Konzolové programy v Qt 4 – 2 (práce s HTTP a FTP)

    Zdravim,

    mozno mi niekto bude vediet poradit - ked som posledne robil s metodami ktore pracuju s HTTP/HTTPS napriek tomu ze Qt network je deklarovane ako asynchronne na Windows strojoch to sposobovalo "zamrznutie" UI aplikacie pri poziadavkach na server. Ked som to prehnal cez gdb tak Qt vytvoralo cca 5-6 threadov na kazde volanie. Nevie niekto cim to moze byt sposobovane? Vyskytovalo sa to len na Windows, Qt bolo verzie 4.2.2.

    David Watzke avatar 1.9.2009 00:44 David Watzke | skóre: 74 | blog: Blog... | Praha
    Rozbalit Rozbalit vše Re: Konzolové programy v Qt 4 – 2 (práce s HTTP a FTP)

    Zkus aktuální verzi Qt (dnes 4.5.2) a případně nahlaš chybu vývojářům (viz web qt.nokia.com). Půjde o windows-specific bug.

    Pokud to zatím potřebuješ obejít, tak síťování dělej v odděleném vlákně QThread.

    “Being honest may not get you a lot of friends but it’ll always get you the right ones” ―John Lennon
    1.9.2009 10:40 Ladicek | skóre: 28 | blog: variace | Havlíčkův brod
    Rozbalit Rozbalit vše Re: Konzolové programy v Qt 4 – 2 (práce s HTTP a FTP)
    Má nějaký smysl, že signál finished spojuješ se slotem gotReply/downloadFinished už v konstruktoru, zatímco všechny ostatní až v metodě run (a to dokonce teprve poté, co spustíš samotné stahování)? Intuitivně bych to všechno dělal na jednom místě (asi v run před zahájením stahování)…
    Ještě na tom nejsem tak špatně, abych četl Viewegha.
    David Watzke avatar 1.9.2009 11:17 David Watzke | skóre: 74 | blog: Blog... | Praha
    Rozbalit Rozbalit vše Re: Konzolové programy v Qt 4 – 2 (práce s HTTP a FTP)
    Jo, má to smysl. V konstruktoru dělám spojení s tím managerem, zatímco v tý metodě spojuju sloty se signály socketu - a ten socket získám teprve po spuštění metody (head) manageru, takže to jinak ani nejde.
    “Being honest may not get you a lot of friends but it’ll always get you the right ones” ―John Lennon
    1.9.2009 11:50 Ladicek | skóre: 28 | blog: variace | Havlíčkův brod
    Rozbalit Rozbalit vše Re: Konzolové programy v Qt 4 – 2 (práce s HTTP a FTP)
    Ha, toho jsem si nevšiml, jak jsem to tak rychle prolítnul. Díky.
    Ještě na tom nejsem tak špatně, abych četl Viewegha.
    1.9.2009 10:54 Jirka
    Rozbalit Rozbalit vše void QTcpServer::incomingConnection ( int socketDescriptor )

    Jak korektne implementovat void QTcpServer::incomingConnection ( int socketDescriptor ) pro potomka tridy QTcpServer? Prijde mi, ze to neni mozne. Ta metoda je virtualni, aby mohla byt prepsana. Ale jeji implementace v QTcpServer vyuziva privatni funkce, takze kdyz ji chce nekdo implementovat znovu, nemuze podle me zajistit stejnou funkcnost.

    David Watzke avatar 1.9.2009 11:18 David Watzke | skóre: 74 | blog: Blog... | Praha
    Rozbalit Rozbalit vše Re: void QTcpServer::incomingConnection ( int socketDescriptor )
    Pokud chceš stejnou funkčnost, tak ji prostě nech jak je. Nemusíš ji reimplementovat za každou cenu. Pokud chceš aby dělala to, co dělá + něco navíc, tak si vytvoř vlastní a volej v ní
    QTcpServer::incomingConnection(socketDescriptor);
    “Being honest may not get you a lot of friends but it’ll always get you the right ones” ―John Lennon
    29.6.2023 09:55 Adilkhatri
    Rozbalit Rozbalit vše Re: Konzolové programy v Qt 4 – 2 (práce s HTTP a FTP)
    A to a great degree brilliant blog passage. We are really grateful for your blog passage. fight, law usage You will find an extensive measure of techniques in the wake of heading off to your post. I was absolutely examining for. An obligation of appreciation is all together for such post and please keep it up. Mind blowing work. 먹튀검증

    Založit nové vláknoNahoru

    ISSN 1214-1267   www.czech-server.cz
    © 1999-2015 Nitemedia s. r. o. Všechna práva vyhrazena.