QT socket使用内部自带的超时属性设置连接超时时间

本文探讨如何在QT 5.15.0中通过QNetworkSession设置TCP连接的超时时间,以解决QTcpSocket连接下位机时的超时问题,并介绍了使用废弃标志但仍可用的QNetworkSession进行超时调整的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

QT版本:5.15.0 msvc2019

QTcpSocket操作默认都是异步操作,connectToHost连接也是立刻返回,没有返回值,通过信号获取是否成功,这个问题也不大,但是这个默认超时时间30s有点长,没有明显的其他成员函数可以修改这个超时时间,网上找到一般是这两个方法:
1. 使用waitForConnected改成同步的方式等待,设置等待时间,超时可以选择取消连接,一般需要在线程内操作,不然卡UI
2. 自己建一个QTimer定时器,超时后检查是否已经连接了,没连接可以选择取消连接

在查看源码时发现了第三种方法:
在qabstractsocket.cpp源码文件的QAbstractSocketPrivate::_q_connectToNextAddress()函数中,
创建了一个连接超时的定时器,默认使用QNetworkConfigurationPrivate::DefaultTimeout(30000ms)值作为超时时间,同时判断socket的_q_networksession属性是否存在,存在则从属性获取超时时间,_q_networksession属性为QSharedPointer<QNetworkSession>对象
void QAbstractSocketPrivate::_q_connectToNextAddress()
{
    ......

    if (!connectTimer) {
        connectTimer = new QTimer(q);
        QObject::connect(connectTimer, SIGNAL(timeout()),
                                    q, SLOT(_q_abortConnectionAttempt()),
                                    Qt::DirectConnection);
    }
    int connectTimeout = QNetworkConfigurationPrivate::DefaultTimeout;// 默认值为30000ms
#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
    QSharedPointer<QNetworkSession> networkSession = qvariant_cast< QSharedPointer<QNetworkSession> >(q->property("_q_networksession"));
    if (networkSession) {
        QNetworkConfiguration networkConfiguration = networkSession->configuration();
        connectTimeout = networkConfiguration.connectTimeout();
    }
#endif
    connectTimer->start(connectTimeout);

    ......
}
    

实际内部已经定义了一个QTimer,判断来连接是否超时,只需要设置这个超时时间即可

在文档中QNetworkSession标志为已经废弃,不建议使用,不过暂时没找到其他方法设置,就先用着,设置超时方法如下:

QNetworkConfigurationManager manager;
QNetworkConfiguration config = manager.defaultConfiguration();
config.setConnectTimeout(3000);
QSharedPointer<QNetworkSession> spNetworkSession(new QNetworkSession(config));
socket->setProperty("_q_networksession", QVariant::fromValue(spNetworkSession));

之所以需要设置短的超时时间,是因为项目使用QModbusTcpClient连接下位机,经常出现连接超时,重连又会成功,需要缩短超时时间,以达到快速连接上下位机的目的。连接超时具体原因暂时没找到。使用wireShark查看消息,发现PC端发送SYN握手信息后,下位机回复了RST ACK,连续多次都是这样子。

网上查找到的解决方法都不行

1. Qt默认使用IPv6连接的,看了拦截的消息,使用的是IPv4。也特意修改连接参数添加指定IPv4协议connectToHost(strIP, port, QIODevice::ReadWrite, QAbstractSocket::IPv4Protocol);

2. 可能是代理问题造成的,那么设置成无代理也没有解决

QNetworkProxyFactory::setUseSystemConfiguration(false);
socket->setProxy(QNetworkProxy::NoProxy);

3. 设置socket option,可能有点效果(效果更多估计是连接完成后),不过依然出现连接超时

socket->setSocketOption(QAbstractSocket::LowDelayOption, 1);
socket->setSocketOption(QAbstractSocket::KeepAliveOption, 1);

还有设置收发buffer大小

socket->setSocketOption(QAbstractSocket::SendBufferSizeSocketOption, 512);
socket->setSocketOption(QAbstractSocket::ReceiveBufferSizeSocketOption, 512);

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值