Russian Qt Forum

Qt => Работа с сетью => Тема начата: 28515 от Август 15, 2013, 21:14



Название: Проверка доступности удаленного хоста средствами Qt (QTcpSocket)
Отправлено: 28515 от Август 15, 2013, 21:14
Доброго времени суток. Решил написать что-то вроде пингера (скорее для общего развития, чем для работы), посмотрел в сторону winapi - стало печально, парсил вывод QProcess-ping.exe - замучался с кодировками. Остановился на QTcpSocket. Вопрос в том, на сколько корректно использовать сокеты для проверки доступности хоста. И какие подводные камни могут быть в случае многопоточной реализации...пусть будет 50 хостов.


Название: Re: Проверка доступности удаленного хоста средствами Qt (QTcpSocket)
Отправлено: NicK от Август 15, 2013, 21:30
QProcess вполне справляется с этой задачей.
Код:
bool GlobalStuff::PING(const QString &host_address, bool show_results)
{
    if(host_address.isEmpty())return false;

#ifdef DEBUG
        qDebug()<<"core: trying to ping host:"<<host_address;
#endif
        bool boolRESULT=false;

        int ping_timeout=500;
        QString exe_path;
        #ifdef Q_WS_WIN
            exe_path=getwindir()+"\\system32\\ping.exe";
        #endif
        #ifdef Q_WS_X11
            exe_path="/bin/ping";
        #endif

       exe_path=global_settings->value("main/ping",exe_path).toString();
       ping_timeout=global_settings->value("main/SETTINGS_PING_TIMEOUT",ping_timeout).toInt();
       if (ping_timeout<=0)ping_timeout=500;

        if(!QFile::exists(exe_path))
        {
#ifdef DEBUG
            qDebug()<<"core: ERROR:"<<exe_path<<"not found!";
#endif
            boolRESULT=false;
        }
        else
        {
            //qApp->setOverrideCursor(Qt::WaitCursor);

            QStringList arguments;
            #ifdef Q_WS_WIN
                QTextCodec::setCodecForCStrings(QTextCodec::codecForName("cp-866"));
                arguments<<host_address;
            #endif
            #ifdef Q_WS_X11
                QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
                arguments<<host_address<<"-c 1";
            #endif

            QProcess myProcess;
            myProcess.start(exe_path,arguments);
            myProcess.waitForFinished(ping_timeout);

            QStringList strlstPingResults;
            strlstPingResults<<myProcess.readAll();
            myProcess.deleteLater();

            QString strResult="";
            for (int i=0;i<=strlstPingResults.count()-1;i++)
            {
#ifdef DEBUG
                qDebug()<<"core: ping results:"<<strlstPingResults[i];
#endif
                strResult='\n'+strlstPingResults[i];
                boolRESULT=strlstPingResults[i].contains("ttl",Qt::CaseInsensitive);
                if (boolRESULT)break;
            };

            //qApp->restoreOverrideCursor();

            if ((show_results)&&(boolRESULT))QMessageBox::information(0,host_address,strResult,QMessageBox::Ok);
        }


        return boolRESULT;
}


Название: Re: Проверка доступности удаленного хоста средствами Qt (QTcpSocket)
Отправлено: 28515 от Август 15, 2013, 21:42
Всё-таки QProcess. Спасибо. А по второму вопросу - ни каких косяков не вылезло?


Название: Re: Проверка доступности удаленного хоста средствами Qt (QTcpSocket)
Отправлено: NicK от Август 15, 2013, 21:47
про QTcpSocket ничего сказать не могу, а с запуском QProcess из отдельного потока проблем не было.


Название: Re: Проверка доступности удаленного хоста средствами Qt (QTcpSocket)
Отправлено: 28515 от Август 15, 2013, 22:04
Большое спасибо.


Название: Re: Проверка доступности удаленного хоста средствами Qt (QTcpSocket)
Отправлено: Bepec от Август 15, 2013, 22:13
Проблема только в одном - пинг может проходить, а хост может быть недоступен :D Точнее его необходимая для работы часть аля ftp сервер или сервис :D


Название: Re: Проверка доступности удаленного хоста средствами Qt (QTcpSocket)
Отправлено: 28515 от Август 15, 2013, 22:31
В смысле недоступна служба? Это критично. Тогда, в случае с M$, это работа с WMI - опять winapi... Или есть альтернатива?


Название: Re: Проверка доступности удаленного хоста с&#
Отправлено: voral от Август 15, 2013, 23:25
Не забывайте так же, что пинг можно запретить. Т.е сервис может быть и доступен - а "не пингуется". Самый верный способ запросить именно то соединение, которое необходимо. Только не переусердствуйте и не шлите запросы часто - можно и бан получить.

Опять же (тем более, что интерес скорее учебный) - можно тогда и расширенную логику реализовать. Как пример цель проверять сайт в онлайне или нет. Т.е. может там и не сайт отвечает, а какаято заглушка.... а может хранить хеш страницы и сравнивать с ним - если отличаются мессага. Вдруг хакнули :)...........

QNetworkManager и Ko - не подходит?


Название: Re: Проверка доступности удаленного хоста средствами Qt (QTcpSocket)
Отправлено: 28515 от Август 15, 2013, 23:44
Честно говоря в сторону QNetworkManager еще не смотрел. Пока попробовал написать на сокетах. Прошу сильно ногами не пинать - код сырой.
Код:
class ConnectToRemoteHost : public QObject
{
    Q_OBJECT
public:
    explicit ConnectToRemoteHost(QObject *parent = 0, const QString & = "0.0.0.0", const int & = 100);
    ~ConnectToRemoteHost();

signals:

public slots:
    void getHostStatus();

private:
    QString hostname;
    QHostInfo info;
    QStringList portList;
    QTcpSocket *socket;
    QTimer * timer;
    bool onlineOfline;

};

ConnectToRemoteHost::ConnectToRemoteHost(QObject *parent, const QString & rhostname, const int & rtimeOut) :
    QObject(parent)
{
    info = QHostInfo::fromName(rhostname);
    if (info.addresses().isEmpty())
    {
        hostname = "0.0.0.0";
    }
    else
    {
        hostname = info.addresses().first().toString();
    }
    socket = new QTcpSocket(this);
    timer = new QTimer(this);
    onlineOfline = false;
    portList << "25"  << "46"  << "50"  << "51"  << "80"
              << "88"  << "110" << "119" << "135" << "137"
              << "139" << "143" << "389" << "445" << "500"
              << "563" << "636" << "993" << "995";
    connect(timer, SIGNAL(timeout()), this, SLOT(getHostStatus()));
    timer->start(rtimeOut);
}

void ConnectToRemoteHost::getHostStatus()
{
    onlineOfline = false;
    for(int i=0; i<portList.length(); i++)
    {

        socket->connectToHost(hostname, portList.at(i).toInt());
        if(socket->waitForConnected(100))
        {
            onlineOfline = true;
            socket->disconnectFromHost();
            break;
        }
    }
    qDebug() << onlineOfline;
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

        ConnectToRemoteHost * host = new ConnectToRemoteHost(0, "www.google.ru", 100);
        QThread *workerThread = new QThread;
        QObject::connect(workerThread, &QThread::started, host, &ConnectToRemoteHost::getHostStatus);
        QObject::connect(workerThread, &QThread::finished, host, &ConnectToRemoteHost::deleteLater);
        host->moveToThread(workerThread);
        workerThread->start();

    return a.exec();
}


QThread - это задел на будущее... Что интересно win7 c включенным брандмауэром увидел.


Название: Re: Проверка доступности удаленного хоста средствами Qt (QTcpSocket)
Отправлено: Bepec от Август 16, 2013, 07:04
И через пару десятков запросов вас заблокирует брандмауэр за спам :D


Название: Re: Проверка доступности удаленного хоста средствами Qt (QTcpSocket)
Отправлено: 28515 от Август 16, 2013, 10:36
www.google.ru, интервал между запросами 1000 msec - полет нормальный, уже 57 минут. Наверно пойду таким путем. Теперь возник другой вопрос. Правильнее было бы сделать возможным добавлять новые хосты (из гуи...в будущем...будет еще динамическое добавление виджетов - это уже в другой ветке форума), и ничего кроме динамического массива указателей на объекты написанного выше класса в голову не приходит. Я правильно рассуждаю?


Название: Re: Проверка доступности удаленного хоста средствами Qt (QTcpSocket)
Отправлено: neversleep от Август 16, 2013, 17:04
Ну, гугл - не из слабаков :) ИХМО, было бы лучше, сначала пропинговать весь список хостов, отсеять не пингующиеся, и только их уже проверять попыткой подключения. Но я так наверно никогда и не пойму, к чему все эти костыли с QProcess :) Ведь есть специально предназначенные для этого ф-ции, пускай и платформо-зависимые. http://www.prog.org.ru/index.php?topic=21185.msg145635#msg145635


Название: Re: Проверка доступности удаленного хоста средствами Qt (QTcpSocket)
Отправлено: Bepec от Август 16, 2013, 22:36
Костыли ибо пинг != работающая система.

Зависла служба тебе нужная и всё, аллес капут. Но пинг идёт и не чешется :D


Название: Re: Проверка доступности удаленного хоста с&#
Отправлено: 28515 от Август 16, 2013, 23:45
Ну в первом приближении что-то вырисовывается.

Костыли ибо пинг != работающая система.

Зависла служба тебе нужная и всё, аллес капут. Но пинг идёт и не чешется :D

Именно! Опыт показывает, что работающий пинг еще не означает, что сервер жив. Пинг слишком низкоуровневый, что бы являться показателем работоспособности удаленной системы. Другой вопрос, как оценивать эту работоспособность. По идее оценка должна быть комплексной, что нить вроде загруженность проца, оперативы, состояние контрольных служб... А вот тут без winapi не обойтись. Над этим еще работать и работать.


Название: Re: Проверка доступности удаленного хоста средствами Qt (QTcpSocket)
Отправлено: Bepec от Август 17, 2013, 10:23
Я решил просто - установкой простейшей службы, которая откликается по порту. Есть отклик - служба работоспособна/система загружена/всё хорошо.


Название: Re: Проверка доступности удаленного хоста средствами Qt (QTcpSocket)
Отправлено: 28515 от Август 18, 2013, 20:47
В целом задача решена, остались эстетические моменты, допиливание GUI и дополнительные обвесы.
 (http://www.imageup.ru/img165/1453870/pinger.jpg)
Всем спасибо! :)