Table of Contents

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 QTcpServer. Vytvořený objekt poslouchá metodou 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 standardně využívaných. Při příchozím spojení je emitován signál 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ý 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 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();
}