10 Stimmen

QTcpSocket-Client automatische erneute Verbindung

Ich versuche, einen Code zu schreiben, der periodisch versucht, eine Verbindung zum Server mit QTcpSocket herzustellen, bis der Server hochgefahren und bereit ist. Der Client sollte auch automatisch und periodisch erneut versuchen, eine Verbindung herzustellen, wenn der Server nicht erreichbar ist, bis er wieder verfügbar ist oder der Benutzer das Programm manuell schließt.

Was ich gemacht habe, besteht darin, die verbundenen und Fehler-Signale von QTcpSocket zu abonnieren. Wenn ich das Fehler-Signal abfange, rufe ich im Grunde genommen die Methode connectToHost erneut auf.

Mein Code versucht periodisch, eine Verbindung zum Host herzustellen, bis der Server bereit ist (dieser Teil funktioniert gut). Das Problem ist jedoch, dass er sich bei einem nicht verfügbaren Server nie wieder verbinden kann. Wenn die Verbindung unterbrochen ist, erhalte ich wie erwartet einen RemoteHostClosedError. Aber nachdem ich die Methode connectToHost erneut im selben Methodenaufruf (wo ich RemoteHostClosedError abfange) aufgerufen habe, passiert nichts. Nicht einmal das Fehler-Signal wird vom QTcpSocket-Objekt ausgelöst.

Ich gebe meinen Code unten an.

TcpServerConnector::TcpServerConnector(SocketSettings socketSettings, QObject* parent)
: QObject(parent), socket(new QTcpSocket())
{
    this->connect(this->socket, SIGNAL(connected()), this, SLOT(connectionSuccess_Handler()), Qt::DirectConnection);
    this->connect(this->socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(connectionError_Handler(QAbstractSocket::SocketError)), Qt::DirectConnection);
}

void TcpServerConnector::connectionError_Handler(QAbstractSocket::SocketError error)
{
    switch (error)
    {
    case QAbstractSocket::AddressInUseError:
        this->logger.log(LogLevel::ERR, "SOCKET ERROR: Adresse wird bereits verwendet");
        break;
    case QAbstractSocket::ConnectionRefusedError:
        this->logger.log(LogLevel::ERR, "SOCKET ERROR: Verbindung abgelehnt");
        break;
    case QAbstractSocket::HostNotFoundError:
        this->logger.log(LogLevel::ERR, "SOCKET ERROR: Host nicht gefunden");
        break;
    case QAbstractSocket::RemoteHostClosedError:
        this->logger.log(LogLevel::ERR, "SOCKET ERROR: Remote-Host geschlossen");
        break;  
    }

    this->socket->abort();
    this->socket->close();
    this->logger.log(LogLevel::DEBUG, "Neu verbinden...");
    SystemUtil::sleepCurrentThread(1000);
    this->socket->connectToHost(ip_address, port);
}

}

Ich überprüfe den Zustand des QTcpSocket vor und nach dem Aufruf der Methode connectToHost (die letzte Zeile, die ich hier angegeben habe). Vor dem Aufruf von connectToHost ist der Zustand UnconnectedState und nach dem Aufruf von connectToHost wird der Zustand Connecting. Nichts Unerwartetes. Allerdings kann er weder eine Verbindung zum Server herstellen, noch ein Fehler-Signal auslösen.

Irgendwelche Ideen?

Hinweis: Die connectToHost-Methode von QTcpSocket wird intern beim ersten Mal aufgerufen.

6voto

Furkan Punkte 663

Für diejenigen, die möglicherweise auf eine ähnliche Situation stoßen, hat die Reset-Methode des QTcpSocket das Problem gelöst.

1voto

user2572422 Punkte 11

Ich war in dieser Situation, das ist die Lösung:

    connect(&tcpClient, SIGNAL(disconnected()), SLOT(ReconnectToHost()));

    void ReconnectToHost(){tcpClient.connectToHost(theServerAddress, port);}

1voto

Veetaha Punkte 783

Ich stand vor einem solchen Problem. Was ich falsch gemacht habe, ist dass ich versucht habe, QTcpSocket::connectToHost() innerhalb eines Slots meiner Klasse aufzurufen, der mit dem Signal QTcpSocket::error() verbunden war. Schließlich fand ich eine Lösung in diesem Beitrag.

Wenn ich mich nicht irre, liegt das Problem darin, dass Sie nicht von innerhalb dieses Slots aus erneut verbinden können, da direkt nachdem das Signal QTcpSocket::error() ausgelöst wird, etwas Wichtiges passiert und der Kontrollfluss von Ihrem Handler zur Methode von QTcpSocket zurückkehrt, die dieses Signal ausgelöst hat, oder Sie auf diese Weise die Logik des Sockets irgendwie brechen.

Keine elegante, aber dennoch Ein-Zeilen-Code-Lösung besteht darin, QMetaObject::invokeMethod(m_socket, "connectToHost", Qt::QueuedConnection); aufzurufen, sobald Ihr handle_socket_error() Slot aufgerufen wurde.

Vorsicht, wenn Sie QMetaObject::invokeMethod auf eine benutzerdefinierte Methode aufrufen, muss sie als Slot registriert sein.

UPD: Schande über mich, aber dieses Problem wird im QAbstractSocket::error() Signal von Qt in der Dokumentation erwähnt.

0voto

sanfirat Punkte 140

Socket.h:

    private slots:
    void reConnectServer(QAbstractSocket::SocketError error);
    private:
    QTcpSocket *mSocket;
    QString mHostname;
    int mPort;

socket.cpp:

    connect(&mSocket,&QTcpSocket::errorOccurred,this,&WorkerClient::reConnectServer);
    void Socket::reConnectServer(QAbstractSocket::SocketError error)
    {
    qDebug()<

`

Denk daran, dies in main.cpp hinzuzufügen:

    qRegisterMetaType();

enum QAbstractSocket::SocketError:

Dieses Aufzählungstyp beschreibt die Socketfehler, die auftreten können. https://doc.qt.io/qt-5/qabstractsocket.html#SocketError-enum

`

0voto

Neo Chen Punkte 1

Ich benutze einen Timer, um dieses Problem zu lösen, und es funktioniert bisher gut.

QTcpSocket _client;
QTimer _timer;

// wenn der Server ausgeschaltet ist, versuchen Sie regelmäßig eine Verbindung herzustellen
connect(&_timer, &QTimer::timeout, this, [&]{_client.connectToHost(QHostAddress("127.0.0.1"),7920);});
_timer.setInterval(5000);
_timer.start();

// wenn verbunden, hören Sie auf zu versuchen
connect(&_client, &QTcpSocket::connected, this, [&]{
    ((QTcpSocket *)QObject::sender())->write("verbunden");
    _timer.stop();
});

// wenn die Verbindung getrennt wird, versuchen Sie es erneut
connect(&_client, &QTcpSocket::disconnected, this, [&]{_timer.start();});

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X