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í
×
    včera 21:29 | Nová verze

    Open source download manager Fatrat povstal z popela. Autor k dvacetiletému výročí projektu přidal do vínku podporu nejnovější knihovny libtorrent, rozhraní portoval na QT6, došlo k nahrazení podpory java rozšíření pythonem. Webové rozhraní bylo přepsáno s podporou mobilních zařízení. Aplikaci je taktéž možno zkompilovat bez podpory GUI. Více informací v releases.

    Max | Komentářů: 4
    včera 21:11 | Bezpečnostní upozornění

    Zranitelnost Broccoli2Shell (CVE-2026-111497) v kompresní knihovně Brotli se netýká pouze Node.js. Ohroženy jsou také aplikace využívající HTTP. Knihovnu používají webové prohlížeče, servery i řada dalších aplikací a technologií, například také Python nebo Bun. Identifikace všech zranitelných komponent může být obtížná, protože knihovna bývá součástí dalších softwarových balíčků nebo je přímo začleněna do spustitelných souborů aplikací.

    Ladislav Hagara | Komentářů: 1
    včera 18:33 | Komunita

    Quad9, švýcarský celosvětově působící neziskový poskytovatel DNS, od 24. listopadu 2026 ukončí své služby ve Francii kvůli soudnímu sporu s katarskou televizní stanicí beIN. Ta požadovala blokování domén, které podle ní nelegálně zpřístupňují sportovní přenosy. Francouzský soud Katarům vyhověl a nařídil (🇫🇷, PDF) Quad9 blokaci zavést, pod hrozbou pokuty 1000 eur denně. Provozovatel příkaz odmítá s tím, že blokace

    … více »
    Pendrekama do nich❗ | Komentářů: 0
    včera 15:22 | Zajímavý článek

    Článek na blogu APNIC vysvětluje, jak správně vytvářet a používat ASPA záznamy — podepsané objekty v RPKI, které uvádějí, kteří poskytovatelé směrování jsou pro dané autonomní číslo (ASN) oprávněni. Síťoví operátoři je mohou využít k ověřování tras BGP a k odhalování úniků tras či podvržených tras.

    vencour | Komentářů: 0
    včera 14:33 | Nová verze

    Byla vydána (𝕏) verze 8.0.0 open source programu pro prolamování hesel hashcat (GitHub, Wikipedie). Přehled novinek v příspěvku v diskusním fóru a pdf.

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

    Byla vydána (𝕏, Bluesky) nová verze 2026.3 linuxové distribuce navržené pro digitální forenzní analýzu a penetrační testování Kali Linux (Wikipedie). Přehled novinek se seznamem 6 nových nástrojů v oficiálním oznámení na blogu.

    Ladislav Hagara | Komentářů: 0
    včera 08:35 | Komunita
    Pořadatelé dalšího ročníku komunitního setkání správců nejen českých a slovenských sítí CSNOG 2027 upozorňují, Call for Abstracts pro blížící se akci (20. a 21. ledna 2027, Zlín) končí už 31. října, tedy na konci tohoto týdne.. … více »
    VSladek | Komentářů: 0
    24.10. 23:22 | Bezpečnostní upozornění

    Výzkumníci ukazují, jak mohou otevřené tunely a IPv6 Extension Headers synchronizovat pakety do krátkých provozních špiček. V kontrolovaném experimentu naměřili přes 180násobnou koncentraci paketového toku vůči průměrné rychlosti odesílání — nikoli 180násobné zvětšení objemu dat. Článek obsahuje metodiku, limity měření i mitigace pro GRE, IPIP a další tunely.

    vencour | Komentářů: 1
    24.10. 12:44 | Pozvánky

    Po velkém úspěchu prvního MobileLinux Hackdaye se vracíme do Českých Budějovic s druhým ročníkem. V pátek 30. října 2026 od 10:00 se v prostorách Jihočeské univerzity uskuteční Embedded & MobileLinux Hackday #2. Těšit se můžete na témata jako Immutable Linux na telefonech (BengalOS), U-Boot a upstream vývoj, AI optimalizace pro embedded systémy nebo otevřený hardware. Nebude chybět praktické hackování, sdílení zkušeností a možnost … více »

    lkocman | Komentářů: 1
    24.10. 00:44 | Bezpečnostní upozornění

    Dne 21. října 2026 vydal projekt Node.js bezpečnostní aktualizace opravující deset zranitelností, včetně jedné umožňující potenciální vzdálené spuštění kódu (RCE). Nejzajímavější je CVE-2026-111497, chyba dekodéru Brotli, kterou objevili výzkumníci využívající OpenAI Codex Security. Chyba je v nativním dekodéru Brotli, nikoli v samotném JavaScriptu. Speciálně vytvořený komprimovaný vstup způsobí, že dekodér zamění

    … více »
    vencour | Komentářů: 15
    Které desktopové prostředí na Linuxu používáte?
     (9%)
     (7%)
     (4%)
     (21%)
     (30%)
     (9%)
     (5%)
     (2%)
     (14%)
     (20%)
    Celkem 2917 hlasů
     Komentářů: 34, poslední včera 08:24
    Rozcestník

    Grafické programy v Qt 4 – 8 (TCP klient)

    16. 9. 2009 | David Watzke | Programování | 10790×

    V tomto díle se naučíme, jak napsat síťového TCP klienta (k serveru s vlastním jednoduchým protokolem) s grafickým rozhraním.

    Co je TCP a kdy jej použít?

    TCP je zkratka Transmission Control Protocol a jde o základní internetový protokol, sloužící k vytvoření spojení mezi počítači a k jejich komunikaci mezi sebou. TCP zaručuje spolehlivé doručení dat ve správném pořadí. Z toho vyplývá i to, kdy je vhodné jej použít: Vždy, když je důležité, aby se veškerá data dostala na druhý konec spojení, i za cenu opakovaného odeslání. Jako příklad lze uvést HTTP (web), FTP, SMTP/POP3/IMAP (e-mail) nebo SSH. Občas je použití TCP ovšem vysloveně nevhodné, a to především v real-time programech, jako jsou třeba hry, kde i když se pár paketů po cestě „ztratí“, tak to moc nevadí. Více informací o TCP je třeba na Wikipedii.

    TCP sockety v Qt

    TCP komunikace v Qt probíhá přes QTcpSocket. To je taková zajímavá třída, která je založená na QIODevice, což mj. znamená, že s ní dá zacházet jako s I/O zařízením. Můžete zapisovat data metodou write() a číst je metodou read() nebo readAll(). Když přijdou nová data, dozvíte se to díky signálu readyRead() a když dojde k chybě, tak přijde řada na signál error(). Pak jsou zde ještě signály specifické pro socket – když se socket připojí nebo odpojí, tak vyšle signál connected() nebo disconnected().

    Než tohle všechno ovšem může začít, nejdříve se musíme někam připojit – na nějaký TCP server, který si s námi bude povídat. To se dělá metodou connectToHost() (nebo ekvivalentním slotem connectToHostImplementation()), které zadáte IP adresu a port, na který se chcete připojit, a případně ještě specifikujete, zda chcete socket otevřít pro čtení i zápis (výchozí) či jinak.

    TODO klient

    Jako ukázku TCP síťování v Qt jsem naprogramoval TODO server-klient záležitost. Pro nezasvěcené: TODO jsou poznámky. Úkoly, které je třeba splnit. Tohle je program, který umožňuje uložit si poznámky na server a přistupovat k nim odkudkoliv. Server najdete v článku Konzolové programy v Qt 4 – 3 (TCP server).

    Funguje to celé tak, jak by se dalo očekávat. Na serveru musí mít uživatel vytvořený účet, což se dělá editací konfiguračního souboru. Poté se klient může přihlásit se svým jménem a heslem (heslo není posláno jako čistý text, odesílá se jeho SHA1 hash) a prohlížet či upravovat svůj seznam položek, který je uložený na serveru.

    Uživatel se nemůže připojit z více míst najednou. Pokud server odpoví, že daný účet je už přihlášen odjinud, dostanete na výběr, zda chcete přihlášení vynutit a „přebrat“ (odpojíte tak to druhé sezení), nebo to vzdát.

    Vymyslel jsem si vlastní jednoduchý protokol, kterým spolu klient a server mezi sebou komunikují. Ukážu zde jeho syntaxi, podle které lze vcelku snadno napsat i vlastního klienta (například do konzole). Příkazy jsou v pořadí, jak za sebou obvykle následují v praxi.

    Příkaz Popis
    LOGIN Server pošle tento příkaz (bez argumentů) hned jak zjistí, že se na něj připojujete. Klient na něj odpovídá stejným příkazem, přičemž jako argumenty (oddělené mezerou) předá přihlašovací jméno a SHA1 hash hesla.
    WRONGLOGIN Server tímto říká, že se pokoušíte přihlásit se špatnými údaji.
    LOGGED Tohle pošle server, když přihlášení proběhne úspěšně. Klient na to obvykle zareaguje příkazem LIST.
    ALREADYLOGGED Server tímto říká, že jste již přihlášen. Můžete se buď odpojit, nebo poslat FORCELOGIN.
    FORCELOGIN Vynucené přihlášení. Posílá jej klient a používá se stejně jako LOGIN. I stejně funguje, ale navíc odpojí případné přihlášení odjinud.
    LIST Klient tímto požádá server o seznam položek.
    LISTEMPTY Server tímto říká, že váš seznam položek je prázdný.
    LISTING Pokud seznam položek není prázdný, server pošle tento příkaz a za ním seznam položek, které jsou oddělené znakem nového řádku, tedy \n.
    ADD Klient pošle tento příkaz serveru, když chce přidat položku do seznamu. Text položky tvoří zbytek příkazu.
    LISTFULL Server tímto říká, že váš seznam položek je plný (v mé implementaci může mít uživatel max. 1000 položek).
    ADDED Server takto odpoví, pokud byla položka úspěšně uložena. Zbytek příkazu tvoří text položky.
    REMOVE Klient pošle tento příkaz, když chce smazat položky ze seznamu. Jako argument je třeba předat seznam indexů položek (oddělený mezerami). Indexy začínají od 0 a maximum je 999.
    REMOVED Server tímto říká, že příkaz REMOVE byl vyřízen. Za příkazem následuje seznam indexů položek (oddělený mezerami), které byly odstraněny.
    INVALIDCMD Toto server pošle jako odpověď na příkaz, který je neplatný. Můj klient toto nezpracovává, takže v případě, že dojde na tuhle odpověď (nemělo by), vyskočí obecná chybová hláška o neznámém příkazu ze serveru.
    TOOMANYWRONGLOGINS Server tímto říká, že z klientské IP adresy detekoval během poslední chvíle (výchozí = 60 sekund) příliš mnoho chybných pokusů o přihlášení (výchozí = 10). Můj klient toto nezpracovává, protože se přes něj těžko někdo bude pokoušet o bruteforce login. Ale i kdyby, dostane obecnou chybovou hlášku, jako v předchozím případě.

    To je vše. Když se chcete odpojit, použijte metodu disconnectFromHost() nebo slot disconnectFromHostImplementation() (obojí dělá totéž). Pokud pošlete serveru příkaz (jiný než přihlašovací), když nejste přihlášeni, odpojí vás bez další komunikace.

    Co se týče techniky vyvíjení programu, navrhnul jsem si GUI v Designeru a tentokrát mě to asi definitivně přesvědčilo, že to je mnohem efektivnější metoda a že obvykle nemá valný význam navrhovat GUI ručně. K programu je tentokrát přibalený i překlad do češtiny. Všechno si to můžete stáhnout v archívu tcpclient.tar.bz2.

    tcpclient.h: API.

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include <QMainWindow>
    #include <QAbstractSocket>
    #include <QByteArray>
    
    class MyTcpSocket;
    class QTcpSocket;
    class QLabel;
    
    namespace Ui
    {
    	class MainWindow;
    }
    
    class MainWindow : public QMainWindow
    {
    	Q_OBJECT
    
    public:
    	MainWindow(QWidget *parent = 0);
    
    private:
    	Ui::MainWindow *ui;
    	QTcpSocket* socket;
    	QLabel* statusLabel;
    
    	void setStatus(const QString& statusmsg);
    
    	void login(bool force = false);
    	void socketWrite(QByteArray data);
    	void lockGui(bool lock = true);
    	void unlockGui();
    
    private slots:
    	void doConnect();
    	void gotConnected();
    	void gotDisconnected();
    	void gotError(QAbstractSocket::SocketError error);
    	void handleReply();
    
    	void addItem();
    	void removeSelectedItems();
    };
    
    #endif // MAINWINDOW_H
    

    tcpclient.cpp:

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    
    #include <QtGui>
    #include <QtNetwork>
    
    MainWindow::MainWindow(QWidget *parent)
    	: QMainWindow(parent), ui(new Ui::MainWindow)
    {
    	// použijeme navržené GUI
    	ui->setupUi(this);
    
    	// vytvoříme socket
    	socket = new QTcpSocket(this);
    	// a připojíme jeho signály na sloty, které je zpracují
    	connect(socket, SIGNAL(connected()), SLOT(gotConnected()));
    	connect(socket, SIGNAL(disconnected()), SLOT(gotDisconnected()));
    	connect(socket, SIGNAL(error(QAbstractSocket::SocketError)),
    			SLOT(gotError(QAbstractSocket::SocketError)));
    	connect(socket, SIGNAL(readyRead()), SLOT(handleReply()));
    
    	// vytvoříme popisek pro zprávy na stavovém řádku
    	statusLabel = new QLabel();
    	statusBar()->addWidget(statusLabel);
    
    	// přiřadíme funkce ovládacím prvkům programu:
    	// tlačítko „Connect“ (Připojit)
    	connect(ui->connBtn, SIGNAL(clicked()), SLOT(doConnect()));
    	// tlačítko „Add“ (Přidat)
    	connect(ui->addBtn, SIGNAL(clicked()), SLOT(addItem()));
    	// vstupní pole pro TODO záznam
    	connect(ui->todoEdit, SIGNAL(returnPressed()), SLOT(addItem()));
    	// tlačítko „Remove…“ (Odstranit vybrané)
    	connect(ui->rmBtn, SIGNAL(clicked()), SLOT(removeSelectedItems()));
    	// položka menu „Connect“ (Připojit)
    	connect(ui->actionConnect, SIGNAL(triggered()), SLOT(doConnect()));
    	// položka menu „Disconnect“ (Odpojit)
    	connect(ui->actionDisconnect, SIGNAL(triggered()),
    		socket, SLOT(disconnectFromHostImplementation()));
    	// položka menu „About Qt“ (O Qt)
    	connect(ui->actionAbout_Qt, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
    
    	// viz níže
    	this->lockGui();
    
    	resize(600, 500);
    }
    
    // zakáže relevantní prvky během čekání na odpověď od serveru
    void MainWindow::lockGui(bool lock)
    {
    	ui->actionDisconnect->setDisabled(lock);
    	ui->addBtn->setDisabled(lock);
    	ui->rmBtn->setDisabled(lock);
    }
    
    // odemkne zmiňované prvky
    void MainWindow::unlockGui()
    {
    	this->lockGui(false);
    }
    
    // zařizuje připojení k serveru
    void MainWindow::doConnect()
    {
    	// zamkne tlačítko a položku v menu „Connect“
    	ui->connBtn->setDisabled(true);
    	ui->actionConnect->setDisabled(true);
    	// nastaví zprávu ve stavovém řádku
    	this->setStatus(tr("Connecting…"));
    
    	// uložíme si IP adresu a port do proměnných
    	QString strAddr = ui->addressEdit->text();
    	int port = ui->portEdit->value();
    
    	QHostAddress addr;
    	// zkontrolujeme platnost formátu IP adresy
    	if(!addr.setAddress(strAddr))
    	{
    		QMessageBox::critical(this, tr("Invalid IP address"),
    				      tr("You've entered an invalid IP address!"));
    		ui->addressEdit->setFocus();
    		return;
    	}
    
    	// zahájíme připojování
    	socket->connectToHost(addr, port);
    }
    
    // zapíše data do socketu
    void MainWindow::socketWrite(QByteArray data)
    {
    	socket->write(data);
    	// zajistí okamžitý zápis
    	socket->flush();
    }
    
    // nastaví zprávu ve stavovém řádku
    void MainWindow::setStatus(const QString& statusmsg)
    {
    	QString status = QDate::currentDate().toString(Qt::SystemLocaleShortDate)
    			 + " " + QTime::currentTime().toString() + " – " + statusmsg;
    	statusLabel->setText(status);
    }
    
    // provede se po úspěšném připojení
    void MainWindow::gotConnected()
    {
    	this->setStatus(tr("Successfully connected!"));
    
    	// odemkneme v menu akci pro odpojení a zamkneme tu pro připojení
    	ui->actionDisconnect->setEnabled(true);
    	// odemkneme ovládací prvky pro komunikaci se serverem
    	this->unlockGui();
    }
    
    // provede se po odpojení od serveru
    void MainWindow::gotDisconnected()
    {
    	this->setStatus(tr("Disconnected!"));
    
    	// vyprázdní seznam a patřičně odemkne/zamkne ovl. prvky
    	ui->listWidget->clear();
    	this->lockGui();
    	ui->connBtn->setEnabled(true);
    	ui->actionDisconnect->setDisabled(true);
    	ui->actionConnect->setEnabled(true);
    }
    
    // zpracuje chybu od socketu
    void MainWindow::gotError(QAbstractSocket::SocketError error)
    {
    	qDebug() << "gotError" << error;
    
    	// informujeme program o odpojení
    	this->gotDisconnected();
    	// chybu zobrazíme ve stavovém řádku i v chybovém dialogu
    	this->setStatus(socket->errorString());
    	QMessageBox::critical(this, tr("Network error"), socket->errorString());
    }
    
    // zpracuje odpověď či příkaz, který přišel serveru
    void MainWindow::handleReply()
    {
    	// příchozí data
    	QByteArray rawdata = socket->readAll();
    	// argumenty příkazu
    	QList<QByteArray> data = rawdata.split(' ');
    	// samotný příkaz
    	QByteArray command = data.takeFirst();
    
    	qDebug() << "handling data:" << rawdata;
    
    	if(command == "LOGIN")
    	{ // server vyžaduje přihlášení
    		this->login();
    	} else
    	if(command == "LOGGED")
    	{ // úspěšné přihlášení
    		this->setStatus(tr("Listing the TODO items…"));
    		// vyžádáme si výpis položek
    		this->socketWrite("LIST");
    	} else
    	if(command == "LISTEMPTY")
    	{ // server informuje, že seznam položek je prázdný
    		this->setStatus(tr("Your TODO list is empty!"));
    	} else
    	if(command == "LISTFULL")
    	{ // server informuje, že seznam položek je plný
    		this->unlockGui();
    		// zakážeme tlačítko pro přidávání položek
    		ui->addBtn->setDisabled(true);
    
    		this->setStatus(tr("Your TODO list is full!"));
    		QMessageBox::critical(this, tr("Your TODO list is full!"),
    				      tr("Server says that your TODO list is full. "
    					 "You need to remove some items."));
    	} else
    	if(command == "LISTING")
    	{ // server posílá seznam položek
    		// uložíme si odpověď bez příkazu
    		QString list = rawdata.right( rawdata.size()-command.size()-1 );
    		// řetězce jsou v odpovědi odděleny znakem \n, takže je převedeme na skutečný seznam
    		ui->listWidget->addItems(list.split(QChar('\n'), QString::SkipEmptyParts));
    	} else
    	if(command == "ADDED")
    	{ // server informuje o úspěšném přidání položky do seznamu
    		this->unlockGui();
    		ui->todoEdit->clear();
    		this->setStatus(tr("Your TODO item has been successfully saved on the server"));
    
    		QString item = rawdata.right( rawdata.size()-command.size()-1 );
    		ui->listWidget->addItem(item);
    	} else
    	if(command == "REMOVED")
    	{ // server informuje o úspěšném odstranění položek ze seznamu
    		// seznam indexů odstraněných položek
    		QList<QByteArray> indexes = rawdata.right( rawdata.size()-command.size()-1 ).split(' ');
    
    		int i = indexes.size() – 1;
    		// smaže položky i ze seznamu v GUI
    		while(i >= 0)
    		{
    			const QByteArray* index = &indexes.at(i--);
    			delete ui->listWidget->takeItem(index->toInt());
    		}
    
    		this->unlockGui();
    		this->setStatus(tr("Selected items had been removed successfully"));
    	} else
    	if(command == "ALREADYLOGGED")
    	{ // server říká, že daný uživatel je již připojen
    		// dialog s dotazem (vynutit přihlášení?)
    		QMessageBox::StandardButton r = QMessageBox::warning(this, tr("User already logged in!"),
    					     tr("Your account is already logged in, probably "
    						"from somewhere else. Do you want to force the login "
    						"and disconnect the other client?"),
    					     QMessageBox::Yes|QMessageBox::No, QMessageBox::No);
    
    		if(r == QMessageBox::Yes)
    			this->login(true);
    		else // pokud uživatel nechce vynutit připojení, tak se odpojíme
    			socket->disconnectFromHost();
    	} else
    	if(command == "WRONGLOGIN")
    	{ // server informuje o neúspěšném přihlášení na základě špatných údajů
    		// na chvíli odpojíme informování o chybách – jde o (na první pohled úspěšný)
    		// pokus o eliminaci dvou chybových dialogů na sobě
    		socket->disconnect(SIGNAL(error(QAbstractSocket::SocketError)));
    		// zobrazíme chybový dialog
    		QMessageBox::critical(this, tr("Wrong login"),
    				      tr("You've entered a wrong username or password!") + "\n" +
    				      tr("Connection has been closed by the remote server."));
    		// a po zavření dialogu signál opět připojíme
    		connect(socket, SIGNAL(error(QAbstractSocket::SocketError)),
    				SLOT(gotError(QAbstractSocket::SocketError)));
    	} else
    	{
    		QMessageBox::critical(this, tr("Unknown command from the server"),
    				      tr("Server has sent an unknown command which could mean "
    					 "that your client version is outdated."));
    	}
    }
    
    // pošle na server požadavek o přihlášení
    void MainWindow::login(bool force)
    {
    	// získáme z GUI uživatelské jméno
    	QString user = ui->userEdit->text();
    	// a zkontrolujeme, jestli náhodou neobsahuje mezery
    	if(user.contains(QChar(' ')))
    	{
    		this->gotDisconnected();
    		// mezery v uživatelském jménu nemáme rádi
    		QMessageBox::critical(this, tr("Invalid username"),
    				      tr("The username cannot contain any whitespaces!"));
    		return;
    	}
    
    	this->setStatus(tr("Logging in…"));
    
    	// řetězec s požadavkem
    	QByteArray request;
    
    	// získáme z GUI heslo, ze kterého spočítáme SHA1 hash
    	QString pass = QCryptographicHash::hash(ui->passEdit->text().toAscii(),
    						QCryptographicHash::Sha1).toHex();
    
    	// sestrojíme požadavek ve formátu LOGIN uživatel heslo_v_sha1
    	request += QString("LOGIN %1 %2").arg(user).arg(pass);
    
    	// pokud jde o vynucený login, použijeme příkaz FORCELOGIN místo LOGIN
    	if(force)
    		request.prepend("FORCE");
    
    	// a odešleme jej
    	this->socketWrite(request);
    }
    
    // přidá položku do seznamu na server
    void MainWindow::addItem()
    {
    	QByteArray request, tmp;
    	// přidáme si do požadavku text položky
    	request += ui->todoEdit->text();
    	// končíme, pokud je prázdný
    	if(request.isEmpty())
    		return;
    
    	// přidáme datum a čas, pokud jsou zaškrtlá odpovídající pole
    	if(ui->withTime->isChecked() || ui->withDate->isChecked())
    		request.prepend("- ");
    	if(ui->withTime->isChecked())
    	{
    		tmp += QTime::currentTime().toString("HH:mm' '");
    		request.prepend(tmp);
    		tmp.clear();
    	}
    	if(ui->withDate->isChecked())
    	{
    		tmp += QDate::currentDate().toString(Qt::SystemLocaleShortDate);
    		request.prepend(tmp + " ");
    	}
    
    	// přidáme na začátek požadavku příkaz
    	request.prepend("ADD ");
    
    	// nastavíme status, zamkneme GUI
    	this->setStatus("Adding the item…");
    	this->lockGui();
    
    	//qDebug() << request;
    
    	// a odešleme požadavek
    	this->socketWrite(request);
    }
    
    // odstraní vybrané položky ze serveru
    void MainWindow::removeSelectedItems()
    {
    	// získáme seznam označených položek
    	QList<QListWidgetItem*> items = ui->listWidget->selectedItems();
    	// pokud je seznam prázdný, tak o tom informujeme přes status a končíme
    	if(items.isEmpty())
    	{
    		this->setStatus(tr("No item(s) selected for removal!"));
    		return;
    	}
    
    	// seřadíme indexy od nejmenšího po největší
    	QList<int> rows;
    	foreach(const QListWidgetItem* item, items)
    		rows << ui->listWidget->row(item);
    	qSort(rows);
    
    	QByteArray request;
    	// sestrojíme požadavek
    	foreach(int row, rows)
    		request += " " + QByteArray::number(row);
    
    	request.prepend("REMOVE");
    
    	// nastavíme status a zamkneme GUI
    	this->setStatus(tr("Removing selected items…"));
    	this->lockGui();
    
    	//qDebug() << "remove request:" << request;
    
    	// odešleme požadavek
    	this->socketWrite(request);
    }
    

    main.cpp: Novinkou je zde nastavení kódování (UTF-8) pro céčkové řetězce. Díky tomu se na server korektně odešlou položky obsahující české znaky.

    #include <QApplication>
    #include <QLocale>
    #include <QTranslator>
    #include <QTextCodec>
    #include "mainwindow.h"
    
    int main(int argc, char *argv[])
    {
    	QApplication a(argc, argv);
    	a.setApplicationName("tcpclient");
    
    	{
    		QTextCodec* unicode = QTextCodec::codecForName("UTF-8");
    		// nastavení kódování pro C řetězce
    		QTextCodec::setCodecForCStrings(unicode);
    		QTextCodec::setCodecForTr(unicode);
    	}
    
    	QTranslator tr;
    	tr.load(a.applicationName() + "_" + QLocale::system().name());
    	a.installTranslator(&tr);
    
    	MainWindow w;
    	w.setWindowTitle("TODO client");
    	w.show();
    
    	return a.exec();
    }
    

    qt 8 tcpclient

           

    Hodnocení: 95 %

            š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ář

    limit_false avatar 18.9.2009 13:36 limit_false | skóre: 23 | blog: limit_false
    Rozbalit Rozbalit vše Re: Grafické programy v Qt 4 – 8 (TCP klient)

    Na MainWindow::handleReply() by se celkem hodil ten stavovy automat z Qt 4.6 ;-) .  Nebo rozumne RPC, to dlouho v Qt chybi. Kdysi existovala Qt CORBA, ta se snad uz nevyviji. Bez 3rd party knihoven (jako treba ZeroC Ice) je delani middlewaroidnych zalezitosti v Qt znacne neprijemny.

    When people want prime order group, give them prime order group.
    Bedňa avatar 21.9.2009 10:55 Bedňa | skóre: 34 | blog: Žumpa | Horňany
    Rozbalit Rozbalit vše Re: Grafické programy v Qt 4 – 8 (TCP klient)

    Pekné, a čo tak do ďaľšieho dielu hodit niečo realtime protokoloch.

    KERNEL ULTRAS video channel >>>
    David Watzke avatar 21.9.2009 19:25 David Watzke | skóre: 74 | blog: Blog... | Praha
    Rozbalit Rozbalit vše Re: Grafické programy v Qt 4 – 8 (TCP klient)
    Něco s UDP mám v plánu, i když to bude asi o dost jednodušší záležitost.
    “Being honest may not get you a lot of friends but it’ll always get you the right ones” ―John Lennon
    ISSN 1214-1267   www.czech-server.cz
    © 1999-2015 Nitemedia s. r. o. Všechna práva vyhrazena.