公司客户端软件遇到一个问题,客户端在打开远程控制时候win7电脑会白屏一会,win10电脑正常,最终查到的原因是由于用到QUdpsocket 发送消息用到writeDatagram,第一次发送消息要很久才能返回。
跟踪Qt源码
qint64 QUdpSocket::writeDatagram(const char *data, qint64 size, const QHostAddress &address, quint16 port)
{
Q_D(QUdpSocket);
#if defined QUDPSOCKET_DEBUG
qDebug("QUdpSocket::writeDatagram(%p, %llu, \"%s\", %i)", data, size,
address.toString().toLatin1().constData(), port);
#endif
if (!d->doEnsureInitialized(QHostAddress::Any, 0, address))
return -1;
if (state() == UnconnectedState)
bind();
qint64 sent = d->socketEngine->writeDatagram(data, size, QIpPacketHeader(address, port));
d->cachedSocketDescriptor = d->socketEngine->socketDescriptor();
if (sent >= 0) {
emit bytesWritten(sent);
} else {
d->setErrorAndEmit(d->socketEngine->error(), d->socketEngine->errorString());
}
return sent;
}
if (!d->doEnsureInitialized(QHostAddress::Any, 0, address))这个函数返回慢
然后继续往下跟,
bool QUdpSocketPrivate::doEnsureInitialized(const QHostAddress &bindAddress, quint16 bindPort,
const QHostAddress &remoteAddress)
{
const QHostAddress *address = &bindAddress;
QAbstractSocket::NetworkLayerProtocol proto = address->protocol();
if (proto == QUdpSocket::UnknownNetworkLayerProtocol) {
address = &remoteAddress;
proto = address->protocol();
}
// now check if the socket engine is initialized and to the right type
if (!socketEngine || !socketEngine->isValid()) {
resolveProxy(remoteAddress.toString(), bindPort);
if (!initSocketLayer(address->protocol()))
return false;
}
return true;
}
resolveProxy(remoteAddress.toString(), bindPort);这个函数返回慢
void QAbstractSocketPrivate::resolveProxy(const QString &hostname, quint16 port)
{
QList<QNetworkProxy> proxies;
if (proxy.type() != QNetworkProxy::DefaultProxy) {
// a non-default proxy was set with setProxy
proxies << proxy;
} else {
// try the application settings instead
QNetworkProxyQuery query(hostname, port, QString(),
socketType == QAbstractSocket::TcpSocket ?
QNetworkProxyQuery::TcpSocket :
QNetworkProxyQuery::UdpSocket);
proxies = QNetworkProxyFactory::proxyForQuery(query);
}
// return the first that we can use
for (const QNetworkProxy &p : qAsConst(proxies)) {
if (socketType == QAbstractSocket::UdpSocket &&
(p.capabilities() & QNetworkProxy::UdpTunnelingCapability) == 0)
continue;
if (socketType == QAbstractSocket::TcpSocket &&
(p.capabilities() & QNetworkProxy::TunnelingCapability) == 0)
continue;
proxyInUse = p;
return;
}
// no proxy found
// DefaultProxy here will raise an error
proxyInUse = QNetworkProxy();
}
内部有个判断,标红部分,是否采用网络代理,然后把网络代理关掉就正常了,关闭方法有两种,一种全局的
QNetworkProxyFactory::setUseSystemconfiguration(false);
一种单个的
m_webSocket.setProxy(QNetworkProxy::NoProxy);
设置之后就正常。
但是我们客户端以前版本就没问题,现在升级了qt版本,以前5.6.3升级到5.15.2
然后查了下资料,有人说是qt5.8之后默认采用QNetworkProxy::DefaultProxy,以前默认是QtNetworkProxy::NoProxy,参考以下链接
https://www.cnblogs.com/cppskill/p/11730452.html
但我查了下5.63,5.7的源码和5.15的源码对比了下
inline QNetworkProxyPrivate(QNetworkProxy::ProxyType t = QNetworkProxy::DefaultProxy,
const QString &h = QString(), quint16 p = 0,
const QString &u = QString(), const QString &pw = QString())
: hostName(h),
user(u),
password(pw),
capabilities(defaultCapabilitiesForType(t)),
port(p),
type(t),
capabilitiesSet(false)
{ }
都是一样默认DefaultProxy,所以虽然关闭网络代理可以解决这里还是有些疑惑,
这里记录下
这个问题就和webEngine加载web页面首次加载很慢的问题有点像,网上可以查到很多,也是因为开启了网络代理