QTcpSocket 客户端自动重连

Posted

技术标签:

【中文标题】QTcpSocket 客户端自动重连【英文标题】:QTcpSocket client auto reconnect 【发布时间】:2012-07-22 12:25:33 【问题描述】:

我正在尝试编写一段代码,它会定期尝试使用 QTcpSocket 连接到服务器,直到服务器启动并准备好。客户端还应在服务器关闭时自动并定期尝试重新连接,直到它再次启动或用户手动关闭程序。

我所做的是订阅QTcpSocket的连接和错误信号。当我捕捉到错误信号时,我基本上会再次调用 connectToHost 方法。

我的代码会定期尝试连接到主机,直到服务器准备好(这部分工作正常)。但是,问题是当服务器关闭时,它永远无法重新连接。当连接断开时,我按预期得到 RemoteHostClosedError 。但是,在同一方法中再次调用 connectToHost 方法(我在其中捕获 RemoteHostClosedError)后,我什么也没得到。甚至 QTcpSocket 对象也不会发出错误信号。

我在下面给出了我的代码。

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);

我在调用 connectToHost 方法之前和之后检查 QTcpSocket 的状态(我在这里给出的最后一行)。在调用 connectToHost 之前,状态为 UnconnectedState,在调用 connectToHost 之后,其状态变为 Connecting。没有什么意外。但是,它既不能连接到服务器,也不能发出错误信号。

有什么想法吗?

注意:QTcpSocket 的 connectToHost 方法是第一次在内部调用。

【问题讨论】:

不要从错误处理程序插槽重新连接。 “发出此信号时,套接字可能尚未准备好重新连接尝试。” qt documentation 【参考方案1】:

对于可能遇到类似情况的人,QTcpSocket的reset方法解决了这个问题。

【讨论】:

您可以在解决问题时将自己的答案标记为正确。这样,搜索此内容的人将很快找到解决方案。 请您发布您的解决方案...Tnx ;)【参考方案2】:

我遇到过这种情况, 这是解决方案:

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


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

【讨论】:

断开信号在哪里?它是默认的还是用户定义的?【参考方案3】:

我遇到过这样的问题。 我做错的是我试图QTcpSocket::connectToHost() 从我班的一个插槽中连接到QTcpSocket::error() 信号。最后我在post 中找到了解决方案。

如果我没记错的话,问题是你不能从这个槽中重新连接,因为在QTcpSocket::error() 信号发出并且控制流从你的处理程序返回到QTcpSocket 的方法之后立即发生了一些重要的事情,它发出了这个信号,或者你以某种方式破坏了套接字的逻辑。

调用QMetaObject::invokeMethod(m_socket, "connectToHost", Qt::QueuedConnection); 不是一个优雅但仍然是一行代码的解决方案 一旦你的handle_socket_error() 槽被调用。

注意如果你在自定义方法上调用QMetaObject::invokeMethod,它必须注册为一个槽。

UPD:真丢脸,但 Qt 的 QAbstractSocket::error() 信号 documentation 中提到了这个问题。

【讨论】:

以上是关于QTcpSocket 客户端自动重连的主要内容,如果未能解决你的问题,请参考以下文章

MQTT 客户端自动重连机制

自动重连socket客户端的设计选择

RabbitMQ C#客户端自动重连

python之tcp自动重连

【tcp】 TCP的连接重连&QUIC的连接迁移

QTcpSocket 或 QSslSocket 会自动创建读/写线程吗?