Russian Qt Forum

Qt => Базы данных => Тема начата: Примерный ученик от Октябрь 26, 2009, 12:42



Название: Проверка включения сервера
Отправлено: Примерный ученик от Октябрь 26, 2009, 12:42
Есть клиент, который общается с множеством баз PostgreSQL.
Как можно узнать, включен ли каждый из серверов?
При выполнении команды

QSqlDatabase testPSQL->open()

если база отключена, требуется прорва времени.
Есть ли другой способ?

QT 3.3.3


Название: Re: Проверка включения сервера
Отправлено: NicK от Октябрь 26, 2009, 13:06
Код:
bool PING(QString strServer){
        QStringList strlstPingResults;
        bool boolRESULT=false;

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


        QProcess myProcess;
        myProcess.start("ping", arguments);

        myProcess.waitForFinished(500);
        strlstPingResults<<myProcess.readAll();
        myProcess.deleteLater();

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

        return boolRESULT;
}


Название: Re: Проверка включения сервера
Отправлено: BRE от Октябрь 26, 2009, 13:19
При пинговании можно определить что компьютер в сети, но на нем может быть не запущен сервер PostgreSQL.

Можно попробовать подключиться используя QSocket к нужному хосту по нужному порту. Если подключение произойдет, можно считать что сервер PostgreSQL активен.


Название: Re: Проверка включения сервера
Отправлено: Примерный ученик от Октябрь 26, 2009, 13:25
BRE  т.е. приконнектится? Попробую...


Название: Re: Проверка включения сервера
Отправлено: Примерный ученик от Октябрь 26, 2009, 14:33
Кажись работает. Ед. вопрос, как долго ждать подключения?
Сделал
Код:
		QSocket test;
test.connectToHost(sql.value(1).toString(),sql.value(2).toInt());
int ii=0;
while(test.state()!=QSocket::Connected)
{
ii++;
if (ii==10) break;
qApp->processEvents();
}
if (test.state()==QSocket::Connected)
{
test.disconnect();
QMessageBox::critical( this,"","Есть связь");
}
else
{
QMessageBox::critical( this,"","Нет связи");
}
Десяти прерываний для местных серверов достаточно. А для удаленных?


Название: Re: Проверка включения сервера
Отправлено: BRE от Октябрь 26, 2009, 15:04
Кажись работает. Ед. вопрос, как долго ждать подключения?

Десяти прерываний для местных серверов достаточно. А для удаленных?
Жди пока не подключишься или пока не произойдет ошибка.


Название: Re: Проверка включения сервера
Отправлено: Примерный ученик от Октябрь 26, 2009, 15:41
Т.е ждать сигнала

void connected ()

или

void error ( int )

???


Название: Re: Проверка включения сервера
Отправлено: BRE от Октябрь 26, 2009, 15:54
Т.е ждать сигнала
void connected ()
или
void error ( int )
???
Ну в общем да.
Посмотри как меняются состояния сокета, когда подключение удается и когда нет. Для того что бы решить доступен сервер или нет.


Название: Re: Проверка включения сервера
Отправлено: NicK от Октябрь 26, 2009, 16:28
Пробовал так:
Код:
bool MainWindow::CheckConnection()
    {
            bool boolConnected=false;

            QProgressDialog *conect2hostDialog = new QProgressDialog("Waiting for connection...", "Cancel", 0, 0);
            conect2hostDialog->setModal(true);
            conect2hostDialog->show();
            //--------------------------------------------------------

            QTcpSocket test;
            test.connectToHost(strHostName,strPort.toInt());

            while(test.state()!=QTcpSocket::ConnectedState){
                if (conect2hostDialog->wasCanceled()){boolConnected=false;break;};
                qApp->processEvents();
            };

            if (test.state()==QTcpSocket::ConnectedState){
                boolConnected=true;
                test.disconnect();
                //QMessageBox::critical( this,"",tr("Connection established"));
            }
            else QMessageBox::critical( this,"",tr("Connection to ")+strHostName+":"+strPort+tr(" is failed."));
            //--------------------------------------------------------
            delete conect2hostDialog;

            return boolConnected;
}

Но, после нескольких неудачных попыток MySQL отвечает:
Цитировать
Database open error.

Host 'fedora' is blocked because of many connection errors; unblock with 'mysqladmin flush-hosts' QMYSQL: Unable to connect
MySQL считает мои проверки за ошибки подключения. Что я не так делаю?


Название: Re: Проверка включения сервера
Отправлено: BRE от Октябрь 26, 2009, 16:57
Код
C++ (Qt)
#include <QCoreApplication>
#include <QTcpSocket>
#include <QDebug>
 
int main( int argc, char *argv[] )
{
       QCoreApplication app( argc, argv );
 
       QTcpSocket socket;
       socket.connectToHost( "localhost", 3306 );
       if( socket.waitForConnected() )
       {
               qDebug() << "MySql server active";
       }
       else
       {
               qDebug() << "MySql server not active";
       }
 
       return 0;
}
 


Название: Re: Проверка включения сервера
Отправлено: NicK от Октябрь 26, 2009, 18:42
Для периодической проверки сервера по таймеру этот вариант не подходит.  :(
Как убедить MySQL что такие проверки не "connection eror"?


Название: Re: Проверка включения сервера
Отправлено: BRE от Октябрь 26, 2009, 19:34
Для периодической проверки сервера по таймеру этот вариант не подходит.  :(
Как убедить MySQL что такие проверки не "connection eror"?
disconnect делать не забываешь?
Как часто пытаешься подключаться?

По хорошему нужно посмотреть протокол обмена сервера и клиента mysql.


Название: Re: Проверка включения сервера
Отправлено: Примерный ученик от Октябрь 26, 2009, 21:36
Шпинял в течении часа. PostgresSQL не ругался...
Опрос через каждые 5 сек
Код:
	if (flagTestUsel) return;  // Идет обработка
flagTestUsel=true; // начинаем работу
QSqlQuery sql(MyPSQL); // наша база
sql.exec("SELECT * FROM usel");
int prz=0;
while (sql.next()) // проверка всех серверов
{
QSocket test;
test.connectToHost(sql.value(1).toString(),sql.value(2).toInt());
int ii=0;
while(test.state()!=QSocket::Connected)
{
ii++;
if (ii==10) break;
qApp->processEvents();
}
if (test.state()==QSocket::Connected)
{
prz=1; // есть связь
test.disconnect();
}
else
{
prz=0; // нет связи
}
if (prz!=sql.value(5).toString()) // статус изменился
{
QSqlCursor sCur("usel",true,MyPSQL);
sCur.select("ind="+sql.value(7).toString());
if (sCur.next())
{
QSqlRecord *buffer;
buffer = sCur.primeUpdate();  // запись для обновления
buffer->setValue("prz",prz);
sCur.update();
}
qApp->processEvents();
}
}
textLabel1->setText("Контроль серверов. Пауза в работе");
flagTestUsel=false; // закончили проверку

В логе только сообщения типа

2009-10-26 13:51:58 LOG:  incomplete startup packet


Название: Re: Проверка включения сервера
Отправлено: Примерный ученик от Октябрь 26, 2009, 21:40
Но обмен проходил нормально

А

QTcpSocket socket;

в QT3 не присутствует ;D


Название: Re: Проверка включения сервера
Отправлено: NicK от Октябрь 26, 2009, 23:32
В течение 15-20 минут по таймеру каждые 15 секунд запускается проверка сервера:
Код
C++ (Qt)
bool CheckConnection()
{
           bool boolConnected=false;
 
           QTcpSocket test;
           test.connectToHost(strCONNECTION_SETTINGS_Hostname,strCONNECTION_SETTINGS_Port.toInt());
           qDebug()<<"DEBUG: core: polling server...";
           if( test.waitForConnected() ){
               boolConnected=true;
               qDebug()<<"DEBUG: core: connection established";
               qDebug()<<"DEBUG: core: disconnecting...";
               test.waitForDisconnected();
               qDebug()<<"DEBUG: core: disconnected";
           }
           else {
               boolConnected=false;
               qDebug()<<"DEBUG: core: connection failed";
           };
 
           return boolConnected;
}

Все отлично работает. Удачный коннект и разъединение. Но если через эти 15-20 минут попробовать это:
Код
C++ (Qt)
 {
QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL","mysql_db_core");
       qDebug()<<"DEBUG: core: create connection";
       db.setHostName(strCONNECTION_SETTINGS_Hostname);
       db.setPort(strCONNECTION_SETTINGS_Port.toInt());
       db.setDatabaseName(strCONNECTION_SETTINGS_DBname);
       db.setUserName(strCONNECTION_SETTINGS_Username);
       db.setPassword(strCONNECTION_SETTINGS_Password);
if (boolCONNECTION_SETTINGS_SSL) db.setConnectOptions("CLIENT_SSL=1;CLIENT_IGNORE_SPACE=1"); // use an SSL connection to the server
if (db.open()){
 
...
 
   db.close();
};
 
 };
 qDebug()<<"DEBUG: core: remove connection.";QSqlDatabase::removeDatabase("mysql_db_core");

то на вызове if (db.open()) получаю все то же сообщение о блокировании соединения.
Сами же проверки выполняются и дальше нормально, но базу уже не открыть.


Qt - 4.5.2
ОС- KUbuntu 9.04

Сервер - CentOS release 5.4 (Final) 2.6.18-164.2.1.el5.plus
MySQL - mysql  Ver 14.12 Distrib 5.0.77, for redhat-linux-gnu (i686) using readline 5.1



Название: Re: Проверка включения сервера
Отправлено: BRE от Октябрь 26, 2009, 23:41
Цитировать
По хорошему нужно посмотреть протокол обмена сервера и клиента mysql.

В mysqladmin есть режим ping. Посмотри как это делается там.
Возможно в клиентской библиотеке mysql есть необходимый функционал.


Название: Re: Проверка включения сервера
Отправлено: NicK от Октябрь 27, 2009, 00:19
Цитировать
В mysqladmin есть режим ping. Посмотри как это делается там.
Возможно в клиентской библиотеке mysql есть необходимый функционал.
Спасибо за подсказку.
Нашел вот что: http://knowledgehub.zeus.com/articles/2006/02/27/custom_monitors_for_mysql_in_c (http://knowledgehub.zeus.com/articles/2006/02/27/custom_monitors_for_mysql_in_c)
Попробую копать в эту сторону :)


Название: Re: Проверка включения сервера
Отправлено: lit-uriy от Октябрь 27, 2009, 01:52
NicK, а ты единственный кто к базе подключается. Может кто-то её не рационально использует и она действительно занята?
MySQL вроде использует блокировки для разруливания доступа


Название: Re: Проверка включения сервера
Отправлено: NicK от Октябрь 27, 2009, 10:14
NicK, а ты единственный кто к базе подключается. Может кто-то её не рационально использует и она действительно занята?
MySQL вроде использует блокировки для разруливания доступа

Нет. я не единственный. На самом сервере работает сервис, который постоянно дергает разные данные с базы. но там обыкновенный SELECT выполняется и все.

Блокируется именно мой компьютер, из-за того, что постоянные connect'ы и disconnect'ы QTcpSocket'а воспринимаются как connection errors (kmysqladmin показал ~300 ошибок соединения с моего хоста  за ~15 минут). Если же тупо соединяться к базе через db.open(без проверки MySQL порта через сокет), то никаких ошибок не возникает.

В общем, я вижу сейчас два варианта для проверки сервера: или использовать просто пинг(но так не проверить наличие самого mysql сервера), или реализовывать пинг средствами mysql, как описано по ссылке, приведенной мной выше.


Название: Re: Проверка включения сервера
Отправлено: Примерный ученик от Октябрь 27, 2009, 20:07
Попробуй
уменьшить время ожидания.

Я заложился, что если за 5 сек сервер не отозвался, то он или выключен или
сильно загружен...
Код:
loadPSQL->setConnectOptions("connect_timeout=5");
loadPSQL->open();

С моей точки зрения такое решение наиболее корректное