Question

I'm trying to write a piece of code that periodically tries to connect to the server using QTcpSocket until the server is up and ready. The client should also automatically and periodically try reconnecting when the server is down until it is up again or user manually closes the program.

What I have done is subscribing to the connected and error signals of QTcpSocket. When I catch the error signal, I basically call connectToHost method again.

My code periodically tries to connect to the host until the server is ready (this part works fine). However, the problem is when the server is down it can never reconnect. When the connection is down I get RemoteHostClosedError as expected. But, after calling the connectToHost method again inside the same method (where I catch RemoteHostClosedError) I got nothing. Even the error signal is not emitted by the QTcpSocket object.

I gave my code below.

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: Address is already in use");
        break;
    case QAbstractSocket::ConnectionRefusedError:
        this->logger.log(LogLevel::ERR, "SOCKET ERROR: Connection refused");
        break;
    case QAbstractSocket::HostNotFoundError:
        this->logger.log(LogLevel::ERR, "SOCKET ERROR: Host not found");
        break;
    case QAbstractSocket::RemoteHostClosedError:
        this->logger.log(LogLevel::ERR, "SOCKET ERROR: Remote host closed");            
        break;  
    }


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

}

I check the state of the QTcpSocket before and after calling the connectToHost method (the last line I gave here). Before calling connectToHost the state is UnconnectedState and after calling connectToHost its state becomes Connecting. Nothing unexpected. However, neither it can connect to the server, nor emit an error signal.

Any idea?

Note: The connectToHost metod of QTcpSocket is called internally for the first time.

Was it helpful?

Solution

For the ones who may come across with a similar situation, the reset method of the QTcpSocket solved the problem.

OTHER TIPS

I am was across this situation, this is solution:

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


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

I've faced such a problem. What I did wrong is I tried to QTcpSocket::connectToHost() from withing a slot of my class, connected to QTcpSocket::error() signal. Finally I found a solution in this post.

If I am not mistaken, the problem is you can't reconnect from within this slot, because something important happens right after QTcpSocket::error() signal is emmited and flow of controll returns from your handler to the QTcpSocket's method, which emitted this signal, or so you somehow break the socket's logic that way.

Not an elegant, but still one-line-of-code sollution is to call QMetaObject::invokeMethod(m_socket, "connectToHost", Qt::QueuedConnection); once your handle_socket_error() slot has been called.

Beware if you call QMetaObject::invokeMethod on custom method, it must be registered as a slot.

UPD: Shame on me, but this issue is mentioned in Qt's QAbstractSocket::error() signal documentation.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top