Russian Qt Forum
Ноябрь 23, 2024, 11:31 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Проверка доступности удаленного хоста средствами Qt (QTcpSocket)  (Прочитано 18782 раз)
28515
Гость
« : Август 15, 2013, 21:14 »

Доброго времени суток. Решил написать что-то вроде пингера (скорее для общего развития, чем для работы), посмотрел в сторону winapi - стало печально, парсил вывод QProcess-ping.exe - замучался с кодировками. Остановился на QTcpSocket. Вопрос в том, на сколько корректно использовать сокеты для проверки доступности хоста. И какие подводные камни могут быть в случае многопоточной реализации...пусть будет 50 хостов.
Записан
NicK
Гость
« Ответ #1 : Август 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;
}
Записан
28515
Гость
« Ответ #2 : Август 15, 2013, 21:42 »

Всё-таки QProcess. Спасибо. А по второму вопросу - ни каких косяков не вылезло?
Записан
NicK
Гость
« Ответ #3 : Август 15, 2013, 21:47 »

про QTcpSocket ничего сказать не могу, а с запуском QProcess из отдельного потока проблем не было.
Записан
28515
Гость
« Ответ #4 : Август 15, 2013, 22:04 »

Большое спасибо.
Записан
Bepec
Гость
« Ответ #5 : Август 15, 2013, 22:13 »

Проблема только в одном - пинг может проходить, а хост может быть недоступен Веселый Точнее его необходимая для работы часть аля ftp сервер или сервис Веселый
Записан
28515
Гость
« Ответ #6 : Август 15, 2013, 22:31 »

В смысле недоступна служба? Это критично. Тогда, в случае с M$, это работа с WMI - опять winapi... Или есть альтернатива?
Записан
voral
Гость
« Ответ #7 : Август 15, 2013, 23:25 »

Не забывайте так же, что пинг можно запретить. Т.е сервис может быть и доступен - а "не пингуется". Самый верный способ запросить именно то соединение, которое необходимо. Только не переусердствуйте и не шлите запросы часто - можно и бан получить.

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

QNetworkManager и Ko - не подходит?
« Последнее редактирование: Август 15, 2013, 23:31 от voral » Записан
28515
Гость
« Ответ #8 : Август 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 включенным брандмауэром увидел.
Записан
Bepec
Гость
« Ответ #9 : Август 16, 2013, 07:04 »

И через пару десятков запросов вас заблокирует брандмауэр за спам Веселый
Записан
28515
Гость
« Ответ #10 : Август 16, 2013, 10:36 »

www.google.ru, интервал между запросами 1000 msec - полет нормальный, уже 57 минут. Наверно пойду таким путем. Теперь возник другой вопрос. Правильнее было бы сделать возможным добавлять новые хосты (из гуи...в будущем...будет еще динамическое добавление виджетов - это уже в другой ветке форума), и ничего кроме динамического массива указателей на объекты написанного выше класса в голову не приходит. Я правильно рассуждаю?
Записан
neversleep
Гость
« Ответ #11 : Август 16, 2013, 17:04 »

Ну, гугл - не из слабаков Улыбающийся ИХМО, было бы лучше, сначала пропинговать весь список хостов, отсеять не пингующиеся, и только их уже проверять попыткой подключения. Но я так наверно никогда и не пойму, к чему все эти костыли с QProcess Улыбающийся Ведь есть специально предназначенные для этого ф-ции, пускай и платформо-зависимые. http://www.prog.org.ru/index.php?topic=21185.msg145635#msg145635
Записан
Bepec
Гость
« Ответ #12 : Август 16, 2013, 22:36 »

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

Зависла служба тебе нужная и всё, аллес капут. Но пинг идёт и не чешется Веселый
Записан
28515
Гость
« Ответ #13 : Август 16, 2013, 23:45 »

Ну в первом приближении что-то вырисовывается.

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

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

Именно! Опыт показывает, что работающий пинг еще не означает, что сервер жив. Пинг слишком низкоуровневый, что бы являться показателем работоспособности удаленной системы. Другой вопрос, как оценивать эту работоспособность. По идее оценка должна быть комплексной, что нить вроде загруженность проца, оперативы, состояние контрольных служб... А вот тут без winapi не обойтись. Над этим еще работать и работать.
« Последнее редактирование: Август 16, 2013, 23:47 от 28515 » Записан
Bepec
Гость
« Ответ #14 : Август 17, 2013, 10:23 »

Я решил просто - установкой простейшей службы, которая откликается по порту. Есть отклик - служба работоспособна/система загружена/всё хорошо.
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.153 секунд. Запросов: 21.