最近遇到这个需求,但是发现一个问题,主机可以使用TCP连接但是使用HTTP连接超时(ping超时),于是需要用QT实现ping命令。
网上看了一下,发现竟然没有实现!于是只能自己实现了!
首先需要说明的是,我肯定不希望用QProcess执行"ping.exe”实现,不能跨平台不说,也不优雅。
在网上看到某段TCP代码,给了我很大的启发,原帖在这里,这段代码思路不错,可惜不符合我的要求!
因为我发现实测某些主机可以使用TCP连接但是使用HTTP连接超时(ping超时)。
//判断IP地址及端口是否在线
static bool IPLive(QString ip, int port, int timeout = 1000) {
QTcpSocket tcpClient;
tcpClient.abort();
tcpClient.connectToHost(ip, port);
//100毫秒没有连接上则判断不在线
return tcpClient.waitForConnected(timeout);
}
//判断是否通外网
static bool IsWebOk() {
//能接通百度IP说明可以通外网
return IPLive("115.239.211.112", 80);
}
于是我把上述代码修改为http请求,中间走了不少弯路,不断测试调整,这里直接把最终的代码分享出来吧。
//author:autumoon
//联系QQ:4589968
//日期:2020-12-03
//判断主机是否在线
static bool IsHostOnline(QString strHostName, int nTimeoutmSeconds = 2000);
//判断是否通外网,能连接百度IP说明可以通外网
static bool IsWebOk(){return IsHostOnline("202.108.22.5", 2000);}
实现:
//author:autumoon
//联系QQ:4589968
//日期:2020-12-03
bool HttpDownload::IsHostOnline(QString strHostName, int nTimeoutmSeconds)
{
QNetworkRequest request(strHostName);
request.setRawHeader("Content-Type", "charset='utf-8'");
request.setRawHeader("Content-Type", "application/json");
QNetworkAccessManager* naManager = new QNetworkAccessManager;
QEventLoop eventloop;
QTimer timer;
timer.singleShot(nTimeoutmSeconds, &eventloop, SLOT(quit()));
timer.start();
QNetworkReply* reply = naManager->get(request);
QMetaObject::Connection conRet = QObject::connect(reply, SIGNAL(finished()), &eventloop, SLOT(quit()));
Q_ASSERT(conRet);
eventloop.exec(QEventLoop::ExcludeUserInputEvents);
if (!timer.isActive())
{
//超时,未知状态
disconnect(reply, SIGNAL(finished()), &eventloop, SLOT(quit()));
reply->abort();
reply->deleteLater();
return false;
}
if (reply->error() != QNetworkReply::NoError)
{
reply->abort();
reply->deleteLater();
return false;
}
bool bRes = reply->readAll().length() > 0;
reply->abort();
reply->deleteLater();
return bRes;
}
成功解决问题!使用了定时器解处理超时的问题!执行本函数相当于执行ping,而且跨平台!