====== 11. QT - TCP/IP komunikace ======
Program napsaný pomocí knihoven v QT ukazuje, jak vytvořit jednoduché spojení a vyměnit si mezi serverem a klientem TCP/IP zprávu.
===== Server =====
Serverová část je vytvořena instancí třídy [[https://doc.qt.io/qt-5/qtcpserver.html|QTcpServer]]. Vytvořený objekt poslouchá metodou [[https://doc.qt.io/qt-5/qtcpserver.html#listen|QTcpServer::listen()]] na specifikovaném portu, při praktickém nasazení je třeba dbát na to, aby nebyl zvolený port v konfliktu s některým ze [[https://cs.wikipedia.org/wiki/Seznam_%C4%8D%C3%ADsel_port%C5%AF_TCP_a_UDP|standardně využívaných]]. Při příchozím spojení je emitován signál [[https://doc.qt.io/qt-5/qtcpserver.html#newConnection|QTcpServer::newConnection()]], který je propojen s místní metodou.
Server::Server (QObject *parent) : QObject(parent)
{
server = new QTcpServer (this);
// cekame na spojeni z libovolne IP adresy na portu 1234
if (!server->listen (QHostAddress::Any, 1234))
qDebug() << "nepodarilo se zahajit poslouchani na portu 1234";
// propojeni signalu newConnection se slotem, ktery zpracuje prichozi spojeni
connect (server, SIGNAL(newConnection()), this, SLOT(handleConnection()));
}
Příchozí spojení otevře nový [[https://cs.wikipedia.org/wiki/S%C3%AD%C5%A5ov%C3%BD_socket|síťový socket]]. Z praktických důvodů je dobré počkat, dokud nezačne klient posílat data (resp. dokud se tato data neobjeví ve vstupním bufferu) - k tomu slouží metoda [[https://doc.qt.io/qt-5/qabstractsocket.html#waitForReadyRead|QAbstractSocket::waitForReadyRead]].
void Server::handleConnection()
{
socket = server->nextPendingConnection();
while(!(socket->waitForReadyRead(100)));
QByteArray data = socket->readAll();
qDebug() << data;
socket->write("ACK");
connect (socket, SIGNAL(disconnected()), socket, SLOT(deleteLater()));
socket->disconnectFromHost();
}
Pokud by zůstal socket obsazen, nebude možné znova spustit aplikaci.
Server::~Server()
{
socket->close();
}
===== Klient =====
Client::Client (QString message, QObject *parent) : QObject(parent)
{
socket = new QTcpSocket (this);
// 127.0.0.1
socket->connectToHost ("localhost", 1234);
socket->write(message.toLocal8Bit());
socket->flush();
connect (socket, SIGNAL(disconnected()), socket, SLOT(deleteLater()));
connect (socket, SIGNAL(readyRead()), this, SLOT(readData()));
}
void Client::readData()
{
// precteme data ze serveru
qDebug() << socket->readAll();
}
Client::~Client()
{
socket->close();
}