Domanda

Sono interessato a come QTCPServer funziona dietro le quinte riguardanti i fili e il blocco.QTcpServer ha un metodo listen() che ritorna immediatamente.Se l'ascolto è iniziato con successo il server emetterà il segnale newConnection().Sono interessato a come è l'ascolto del server (è sul thread principale) quando il metodo listen() è restituito.Il solito esempio di un'applicazione console con un qtcpserver è qualcosa del genere:

//main.cpp
int main(int argc, char* argv[])
{
    QCoreApplication app;
    MyServer server;
    app.exec();
}

//MyServer.cpp
MyServer::MyServer(QObject *parent) : QObject(parent)
{
    this->server = new QTcpServer(this);
    connect(server, SIGNAL(newConnection()), this, SLOT(on_newConnection()));
    if (!server->listen(QHostAddress::Any, 1234))
        //do something in case of error
}
void MyServer::on_newConnection()
{
    QTcpSocket* socket = server->nextPendingConnection();
    //do some communication...
}
.

è QTcpServer dipendente da un QCoreApplication (o forse un QRunLoop) esistente e funzionante per ricevere eventi di rete.Può funzionare correttamente senza essere chiamato un QCoreApplication::exec()?

È stato utile?

Soluzione

Ho perforando il codice sorgente dei moduli QtCore e QtNetwork.

Aprentemente, QTcpServer può funzionare in due modalità: Sincrono e Asynchronous .

In modalità Synchronous dopo aver chiamato listen() Il chiamante può chiamare waitForNewConnection() che è un metodo di blocco (il thread Sleep sleever finché qualcuno si collega alla porta di ascolto). In questo modo QTcpServer può funzionare in un thread senza un ciclo di eventi.

in Modalità asincrono QTcpServer emetterà il segnale newConnection() quando è stata accettata una nuova connessione. Ma per essere in grado di farlo ci deve essere un ciclo di evento. Sottostante il QCoreApplication sono il QEventLoop e il QAbstractEventDispatcher (una classe astratta, tipo di calcestruzzo dipende dal sistema operativo, ad esempio QEventDispatcherUNIX). Questo dispatcher eventi può monitorare per le condizioni su prese (rappresentato dai descrittori di file). Ha un metodo registerSocketNotifier(QSocketNotifier*). Questo metodo è chiamato dal costruttore della classe QSocketNotifier, che QTcpServer crea un'istanza di ogni volta che viene chiamato listen(). L'unica chiamata di sistema che viene chiamata quando viene invocato il QTcpServer::listen() è, ovviamente, listen() che restituisce immediatamente, tutta la magia reale avviene quando il loop dell'evento inizia a funzionare. Il loop dell'evento (utilizzando il dispatcher) monitorerà se c'è una determinata condizione sulle prese registrate. Chiama la chiamata di sistema select() che riceve uno o più descrittori di file da monitorare (dal kernel) per determinate condizioni (se ci sono dati da leggere, se i dati possono essere scritti, o se un errore è successo). La chiamata può bloccare il filo fino a quando le condizioni sulle prese sono soddisfatte o possono tornare dopo una certa quantità di passaggi del tempo e le condizioni sulle prese non sono state soddisfatte. Non sono sicuro che QT chiamino select() con un tempo di attesa fornito o senza (per bloccare indefinitamente), penso che sia determinato in modo complicato e modificabile. In tal caso, quando è stata soddisfatta la condizione della presa, il dispatcher eventi avviserà il QSocketNotifier per quella presa, che, in trasfertura, inerfierà il QTcpServer che sta ascoltando la presa, che accetterà la connessione ed emette il segnale newConnection().


.

Quindi il QTcpServer non si chiama per sé nel sistema di eventi-loop / socket-monitoraggio, ma dipende da esso tramite il QSocketNotifier che utilizza per ricezione asincrona delle connessioni.

Quando il metodo sincrono waitForNewConnection() è chiamato semplicemente scavalca tutte le cose QSocketNotifier e chiama accept() che blocca il filo finché non c'è una connessione in entrata.

Altri suggerimenti

La maggior parte delle qt "dietro le quinte" funzionalità si verifica all'interno del ciclo di eventi principale di QCoreApplication: segnali / slot, timer, ecc.
Un esempio sarebbe JavaScript: si legami un evento, ma il ciclo di eventi viene elaborato dal browser.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top