Servidor Fortune

Demuestra cómo crear un servidor para un servicio de red.

Este ejemplo está pensado para ser ejecutado junto con el ejemplo de Cliente de Fortuna o el ejemplo de Cliente de Fortuna Bloqueante.

Captura de pantalla del ejemplo de Fortune Server

Utiliza QTcpServer para aceptar conexiones TCP entrantes, y un simple protocolo de transferencia de datos basado en QDataStream para escribir una fortuna al cliente que se conecta (desde el ejemplo de Cliente de Fortuna ), antes de cerrar la conexión.

class Server : public QDialog
{
    Q_OBJECT

public:
    explicit Server(QWidget *parent = nullptr);

private slots:
    void sendFortune();

private:
    void initServer();

    QLabel *statusLabel = nullptr;
    QTcpServer *tcpServer = nullptr;
    QList<QString> fortunes;
};

El servidor se implementa utilizando una clase simple con una sola ranura, para manejar las conexiones entrantes.

    tcpServer = new QTcpServer(this);
    if (!tcpServer->listen()) {
        QMessageBox::critical(this, tr("Fortune Server"),
                              tr("Unable to start the server: %1.")
                              .arg(tcpServer->errorString()));
        close();
        return;
    }
    QString ipAddress;
    const QList<QHostAddress> ipAddressesList = QNetworkInterface::allAddresses();
    // use the first non-localhost IPv4 address
    for (const QHostAddress &entry : ipAddressesList) {
        if (entry != QHostAddress::LocalHost && entry.toIPv4Address()) {
            ipAddress = entry.toString();
            break;
        }
    }
    // if we did not find one, use IPv4 localhost
    if (ipAddress.isEmpty())
        ipAddress = QHostAddress(QHostAddress::LocalHost).toString();
    statusLabel->setText(tr("The server is running on\n\nIP: %1\nport: %2\n\n"
                            "Run the Fortune Client example now.")
                         .arg(ipAddress).arg(tcpServer->serverPort()));

En su constructor, nuestro objeto Servidor llama a QTcpServer::listen() para configurar un QTcpServer para escuchar en todas las direcciones, en un puerto arbitrario. A continuación, muestra el puerto QTcpServer elegido en una etiqueta, para que el usuario sepa a qué puerto debe conectarse el cliente de fortuna.

fortunes << tr("You've been leading a dog's life. Stay off the furniture.")
         << tr("You've got to think about tomorrow.")
         << tr("You will be surprised by a loud noise.")
         << tr("You will feel hungry again in another hour.")
         << tr("You might have mail.")
         << tr("You cannot kill time without injuring eternity.")
         << tr("Computers are not intelligent. They only think they are.");

Nuestro servidor genera una lista de fortunas aleatorias que puede enviar a los clientes que se conecten.

connect(tcpServer, &QTcpServer::newConnection, this, &Server::sendFortune);

Cuando un cliente se conecta a nuestro servidor, QTcpServer emitirá QTcpServer::newConnection(). A su vez, esto invocará nuestra ranura sendFortune():

void Server::sendFortune()
{
    QByteArray block;
    QDataStream out(&block, QIODevice::WriteOnly);
    out.setVersion(QDataStream::Qt_6_5);

    out << fortunes[QRandomGenerator::global()->bounded(fortunes.size())];

El propósito de esta ranura es seleccionar una línea aleatoria de nuestra lista de fortunas, codificarla en un QByteArray usando QDataStream, y luego escribirla en el socket de conexión. Esta es una forma común de transferir datos binarios utilizando QTcpSocket. Primero creamos un objeto QByteArray y otro QDataStream, pasando el bytearray al constructor de QDataStream. Después establecemos explícitamente la versión del protocolo de QDataStream a QDataStream::Qt_5_10 para asegurarnos de que podemos comunicarnos con clientes de futuras versiones de Qt (ver QDataStream::setVersion()). Continuamos por streaming en una fortuna aleatoria.

    QTcpSocket *clientConnection = tcpServer->nextPendingConnection();
    connect(clientConnection, &QAbstractSocket::disconnected,
            clientConnection, &QObject::deleteLater);

A continuación, llamamos a QTcpServer::nextPendingConnection(), que devuelve el QTcpSocket que representa el lado servidor de la conexión. Conectando QTcpSocket::disconnected() a QObject::deleteLater(), nos aseguramos de que el socket será borrado después de desconectarse.

    clientConnection->write(block);
    clientConnection->disconnectFromHost();
}

La fortuna codificada se escribe usando QTcpSocket::write(), y finalmente llamamos a QTcpSocket::disconnectFromHost(), que cerrará la conexión después de que QTcpSocket haya terminado de escribir la fortuna en la red. Como QTcpSocket trabaja de forma asíncrona, los datos se escribirán después de que esta función retorne, y el control vuelve al bucle de eventos de Qt. El socket se cerrará entonces, lo que a su vez provocará que QObject::deleteLater() lo borre.

Proyecto de ejemplo @ code.qt.io

Vea también Cliente Fortune y Servidor Fortune Threaded.

© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.