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 03:33 | Bezpečnostní upozornění

    V dokumentově orientované databázi MongoDB byla nalezena a v upstreamu již opravena kritická bezpečností chyba CVE-2025-14847 aneb MongoBleed.

    Ladislav Hagara | Komentářů: 0
    včera 23:11 | IT novinky

    Při úklidu na Utažské univerzitě se ve skladovacích prostorách náhodou podařilo nalézt magnetickou pásku s kopií Unixu V4. Páska byla zaslána do počítačového muzea, kde se z pásky úspěšně podařilo extrahovat data a Unix spustit. Je to patrně jediný známý dochovaný exemplář tohoto 52 let starého Unixu, prvního vůbec programovaného v jazyce C.

    🇨🇽 | Komentářů: 0
    včera 15:55 | Komunita

    FFmpeg nechal kvůli porušení autorských práv odstranit z GitHubu jeden z repozitářů patřících čínské technologické firmě Rockchip. Důvodem bylo porušení LGPL ze strany Rockchipu. Rockchip byl FFmpegem na porušování LGPL upozorněn již téměř před dvěma roky.

    🇨🇽 | Komentářů: 5
    včera 15:44 | Zajímavý software

    K dispozici je nový CLI nástroj witr sloužící k analýze běžících procesů. Název je zkratkou slov why-is-this-running, 'proč tohle běží'. Klade si za cíl v 'jediném, lidsky čitelném, výstupu vysvětlit odkud daný spuštěný proces pochází, jak byl spuštěn a jaký řetězec systémů je zodpovědný za to, že tento proces právě teď běží'. Witr je napsán v jazyce Go.

    🇨🇽 | Komentářů: 0
    včera 15:33 | Zajímavý software

    Yazi je správce souborů běžící v terminálu. Napsán je v programovacím jazyce Rust. Podporuje asynchronní I/O operace. Vydán byl v nové verzi 25.12.29. Instalovat jej lze také ze Snapcraftu.

    Ladislav Hagara | Komentářů: 1
    26.12. 18:44 | Komunita

    Od soboty do úterý probíhá v Hamburku konference 39C3 (Chaos Communication Congress) věnovaná také počítačové bezpečnosti nebo hardwaru. Program (jiná verze) slibuje řadu zajímavých přednášek. Streamy a záznamy budou k dispozici na media.ccc.de.

    Ladislav Hagara | Komentářů: 0
    26.12. 13:22 | Zajímavý software

    Byl představen nový Xserver Phoenix, kompletně od nuly vyvíjený v programovacím jazyce Zig. Projekt Phoenix si klade za cíl být moderní alternativou k X.Org serveru.

    🇨🇽 | Komentářů: 7
    26.12. 13:11 | Nová verze

    XLibre Xserver byl 21. prosince vydán ve verzi 25.1.0, 'winter solstice release'. Od založení tohoto forku X.Org serveru se jedná o vůbec první novou minor verzi (inkrementovalo se to druhé číslo v číselném kódu verze).

    🇨🇽 | Komentářů: 0
    26.12. 03:33 | Nová verze

    Wayback byl vydán ve verzi 0.3. Wayback je "tak akorát Waylandu, aby fungoval Xwayland". Jedná se o kompatibilní vrstvu umožňující běh plnohodnotných X11 desktopových prostředí s využitím komponent z Waylandu. Cílem je nakonec nahradit klasický server X.Org, a tím snížit zátěž údržby aplikací X11.

    Ladislav Hagara | Komentářů: 0
    25.12. 14:44 | Nová verze

    Byla vydána verze 4.0.0 programovacího jazyka Ruby (Wikipedie). S Ruby Box a ZJIT. Ruby lze vyzkoušet na webové stránce TryRuby. U příležitosti 30. narozenin, první veřejná verze Ruby 0.95 byla oznámena 21. prosince 1995, proběhl redesign webových stránek.

    Ladislav Hagara | Komentářů: 0
    Kdo vám letos nadělí dárek?
     (33%)
     (1%)
     (23%)
     (1%)
     (1%)
     (1%)
     (11%)
     (12%)
     (17%)
    Celkem 175 hlasů
     Komentářů: 18, poslední 24.12. 15:29
    Rozcestník

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

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

    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.