在写TCP连接程序时,突然发现了这样的错误: socket error: The proxy type is invalid for this operation 发现是翻墙状态下进行了连接,翻回墙内之后正常了。这倒是挺有意思,值得研究一下。
先查了stackoverflow,发现是QNeworkProxy的问题,它的枚举ProxyType
包含了几种类型,前四个是 DefaultProxy
,Socks5Proxy
,NoProxy
,HttpProxy,
,是不是问题在这里?在构造函数里定义了tcpSocket之后,加一行tcpSocket->setProxy(QNetworkProxy::NoProxy);
。现在再到翻墙状态下测试,发现果然正常了。
这样还没完,要追本溯源研究问题。用sublime搜索文件夹F:\Qt5.10.1\5.10.1\Src\qtbase\src\network
,找这个报错信息,最终发现调用路径是这样的:
先是QNativeSocketEngine::connectToHost
{
...
if (!d->checkProxy(address))
return false;
}
然后checkProxy函数
QNativeSocketEnginePrivate::checkProxy
{
......
if (proxy.type() != QNetworkProxy::DefaultProxy &&
proxy.type() != QNetworkProxy::NoProxy) {
// QNativeSocketEngine doesn't do proxies
setError(QAbstractSocket::UnsupportedSocketOperationError,
QNativeSocketEnginePrivate::InvalidProxyTypeString);
return false;
}
......
}
setError函数:
QNativeSocketEnginePrivate::setError
{
......
case InvalidProxyTypeString:
socketErrorString = QNativeSocketEngine::tr("The proxy type is invalid for this operation");
break;
}
原来调用connectToHost
时会先检查代理情况。那么我们试着检查socket的代理类型,用tcpSocket->proxy().type();
分别在翻墙和不翻的状态下运行,结果居然都是0,也就是DefaultProxy
,这怎么回事?这样到checkProxy
应该不报错才对啊?
既然这样,那么就是这个函数用的不对,还看帮助吧,找啊找啊,终于找到这样一个函数[static] QNetworkProxy QNetworkProxy::applicationProxy()
,看解释:
Returns the application level network proxying.
If a QAbstractSocket or QTcpSocket has the QNetworkProxy::DefaultProxy
type, then the QNetworkProxy returned by this function is used.看来应该使用这个才对啊,再拿tcpSocket->proxy().applicationProxy().type();
试验,这下就会发现未翻墙状态是NoProxy
,翻墙状态是HttpProxy!
这样一来就清楚了,但是注意上面的解释有一句:If a QAbstractSocket or QTcpSocket has the QNetworkProxy::DefaultProxy
type。那么为什么socket默认用的是DefaultProxy
而不是NoProxy
?这是出于什么考虑?
接着用Google查,发现QTBUG网站和Qt开发者有一些讨论,一位开发者认为既然Chrome都用了系统代理,为什么我们不能?讨论的内容很多,不想都贴出来了,最后的结果是从Qt 5.8开始,socket默认代理类型是DefaultProxy
。
参考:QTBUG:”the proxy type is invalid for this operation”
Qt开发者的讨论:Should the system proxies default setting be switched to true?