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