Поиск:

Ответ в темуСоздание новой темы Создание опроса
> QTcpSocket и QTcpServer, Проблема с поддержанием соединения 
:(
    Опции темы
Belirafor
  Дата 11.12.2011, 12:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 29
Регистрация: 15.8.2009

Репутация: нет
Всего: нет



Здравствуйте, Уважаемые участники форума. Пишу клиент-серверное приложение. Возникает проблема при поддержке соединения между клиентом и сервером. Нужно, чтобы клиент и сервер постоянно держали соединение.

При запуске сервера все хорошо, а при запуске клиента, он повисает в памяти (окно не отображается с данными). При закрытии сервера, окно появляется вместе с данными, которые передал сервер. Если же сделать tcpSocket->close(); то все хорошо. И сервер работает и клиент отображает данные после запуска. Но по нажатии кнопки обновить, все данные пропадают с окна, поскольку сокет был закрыт. Подскажите как быть? Ниже привожу код сервера и клиента.

Переделал сервер с сигналами и слотами, но не пойму, как мне избежать tcpSocket->close(); и дальнейшего зависания клиента в памяти.

Код


/*Сервер*/
#include "dlginfo.h"
#include "ui_dlginfo.h"
 
DlgInfo::DlgInfo(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::DlgInfo)
{
    ui->setupUi(this);
//    setWindowTitle(QString::fromUtf8("Сервер"));
    setWindowTitle(tr("Сервер"));
 
    StartServer();
 
    connect(ui->pbtn_Start, SIGNAL(clicked()), SLOT(StartServer()));
    connect(ui->pbtn_Stop, SIGNAL(clicked()), SLOT(StopServer()));
}
 
void DlgInfo::StartServer()
{
    tcpServer = new QTcpServer(this);
 
    if(!tcpServer->listen(QHostAddress::Any, 3333))
    {
        ui->txtbrsr_Info->append(tcpServer->errorString());
    }
 
    else
    {
        connect(tcpServer, SIGNAL(newConnection()), SLOT(IncKey()));
        ui->txtbrsr_Info->append(tr("Сервер запущен"));
        ui->pbtn_Start->setDisabled(true);
    }
}
 
void DlgInfo::StopServer()
{
    tcpServer->close();
    ui->txtbrsr_Info->append(tr("Сервер остановлен"));
    ui->pbtn_Start->setEnabled(true);
}
 
void DlgInfo::NewIncConn()
{
    //Информация о подключаемых клиентах
    ui->txtbrsr_Info->append(tr("Входящее соединение"));
}
 
void DlgInfo::IncKey()                //Ждем задание от клиента
{
    NewIncConn();
    tcpSocket = tcpServer->nextPendingConnection();
    tcpSocket->waitForReadyRead();
    QByteArray Key = tcpSocket->readAll();
 
    if(Key == "qryJrnl_SELECT")
    {
        JrnlRefresh();
    }
}
 
void DlgInfo::JrnlRefresh()
{
//    NewIncConn();
//    tcpSocket = tcpServer->nextPendingConnection();
    tcpSocket->write("Ready");                          //Отправляем клиенту сообщение о готовности
 
    tcpSocket->waitForReadyRead();
    QByteArray JrnlSelect = tcpSocket->readAll();       //Считали строку запроса целиком
 
    QSqlQuery qryJrnl_SELECT;
    qryJrnl_SELECT.exec(JrnlSelect);
    qryJrnl_SELECT.next();
 
    do{
        QByteArray pkJrnlID = qryJrnl_SELECT.value(0).toByteArray();
        QString NameJrnl = qryJrnl_SELECT.value(1).toString();
 
        qint32 sl_pkJrnlID = pkJrnlID.size();           //Получаем длину строки, передаваемой клиенту. Делаем для разделения данных, чтобы не пришла "каша"
        tcpSocket->write((char*) &sl_pkJrnlID,4);       //Передаем длину строки клиенту
        tcpSocket->write(pkJrnlID);                     //Передаем id журнала клиенту
 
        qint32 sl_NameJrnl = NameJrnl.toUtf8().size();  //Снова получаем длину строки и не забываем, что передаем ее в utf8, иначе придет "каша"
        tcpSocket->write((char*) &sl_NameJrnl,4);       //Передаем длину строки клиенту
        tcpSocket->write(NameJrnl.toUtf8().data());     //Передаем наименование журнала
 
//        qDebug() << pkJrnlID << NameJrnl;
 
    }while(qryJrnl_SELECT.next());     //Выполняем запрос до тех пор пока не закончатся данные
    tcpSocket->close();                   //Если не закрыть сокет клиент повиснет
}
 
DlgInfo::~DlgInfo()
{
    tcpServer->close();
    delete ui;
}



Код

/*Клиент*/
void MainWindow::fncJournal_Refresh()            //Эта функция вызывается по нажатии кнопки "Обновить"
{
    QTextCodec *codec = QTextCodec::codecForName("UTF-8");  //Указываем кодировку
 
    QByteArray SendKey = ("qryJrnl_SELECT");
    tcpSocket->write(SendKey);                  //Отправляем серверу задание для выполнения запроса
 
    tcpSocket->waitForReadyRead();
    tcpSocket->readAll();                       //Ждем ответа от сервера о готовности
 
    QByteArray qryJrnl_SELECT = ("SELECT pkJrnlID, NameJrnl  FROM rJrnl_tbl ORDER BY NameJrnl DESC");
    tcpSocket->write(qryJrnl_SELECT);
 
 
    QTableWidgetItem *newItem;
    ui->tblwgt_Journal->setRowCount(0);
    ui->tblwgt_Journal->setSortingEnabled(true);
    do
    {
        tcpSocket->waitForReadyRead();
        qint32 sl_pkJrnlID;                                     //Длина принимаемой строки, sl - String Length
        tcpSocket->read((char*) &sl_pkJrnlID,4);                //Читаем длину строки, от сервера
        QByteArray pkJrnlID = tcpSocket->read(sl_pkJrnlID);     //Читаем, ТОЛЬКО, необходимое количество байт, чтобы отделить pkJrnlID от NameJrnl
//        qDebug() << pkJrnlID;
 
        tcpSocket->waitForReadyRead();
        qint32 sl_NameJrnl;
        tcpSocket->read((char*) &sl_NameJrnl,4);
        QByteArray NameJrnl = tcpSocket->read(sl_NameJrnl);
        QString u_NameJrnl = codec->toUnicode(NameJrnl);        //Указываем кодировку, явным образом, чтобы избежать проблем при отображении кириллицы
//        qDebug() << u_NameJrnl;
 
        ui->tblwgt_Journal->insertRow(0);
        newItem = new QTableWidgetItem();newItem->setText(pkJrnlID);
        ui->tblwgt_Journal->setItem(0,0, newItem);
        newItem = new QTableWidgetItem();newItem->setText(u_NameJrnl);
        ui->tblwgt_Journal->setItem(0,1, newItem);
    }while(tcpSocket->bytesAvailable() != 0);
 
    ui->tblwgt_Journal->hideColumn(0);
    ui->tblwgt_Journal->horizontalHeader()->setResizeMode(QHeaderView::ResizeToContents);
    ui->tblwgt_Journal->horizontalHeader()->setStretchLastSection(true);
    ui->tblwgt_Journal->verticalHeader()->setHidden(true);
 
    int RowCnt = ui->tblwgt_Journal->rowCount();
 
    if(RowCnt == 0) {ui->statusBar->showMessage(tr("Записей в базе: 0"));}
 
    else {ui->statusBar->showMessage(tr("Записей в базе: ") + QString::number(RowCnt));}
 
//    tcpSocket->waitForBytesWritten();
    tcpSocket->close();


Народ подскажите, как мне не разрывать соединения с сервером и по нажатии кнопки "Обновить" на клиенте, чтобы данные в нем обновлялись. Не понимаю. Посмотрите исходник, плиз. Очень нужно.

Я так понимаю, каким-то образом нужно вызывать функцию IncKey(), поскольку она получает у меня от клиента инструкции. А если закрывать сокеты, то надо вызывать tcpSocket = tcpServer->nextPendingConnection() для нового соединения. Если я правильно понимаю.

Заранее спасибо.
PM MAIL   Вверх
Belirafor
Дата 12.12.2011, 23:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 29
Регистрация: 15.8.2009

Репутация: нет
Всего: нет



Vingrad как всегда в своем репертуаре. Никто ничего не знает.
PM MAIL   Вверх
voral
Дата 13.12.2011, 01:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 158
Регистрация: 16.3.2008
Где: Иваново

Репутация: нет
Всего: нет



Почему бы вам не убрать опрос сервера в отдельный поток (пусть GUI живет своей жизнью").  так же не заюзать  сигнал-слот, что б не замораживать поток GUI  при помощи waitForReadyRead() в ожидании данных. ну или, хотябы на костыльный случай, повтыкать местами qApp->processEvents();

Читать сразу все в буфре. Как только накопилось нужное кол-во отрезаем от начала и отправляем по этапу (сигнал - слот) в потог GUI для отображения.

PM MAIL WWW   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С/С++: Кроссплатформенное программирование, QT/Gtk+/wxWidgets"
JackYF
Любитель
  • В заголовке темы в квадратных скобках обозначьте используемую вами библиотеку, например: [QT],[GTK],[wx].
  • Если вопрос актуален только для некоторой версии библиотеки, либо, если вы пользуетесь не самой последней версией, укажите это. Например: [QT4], [GTK2].
  • Все начинающие изучать Qt - не забудьте зайти сюда.
  • Проставьте несколько ключевых слов темы, чтобы её можно было легче найти.
  • В вопросе укажите полную версию версию библиотеки, а также все дополнительные используемые программные пакеты.
  • Не забывайте пользоваться кнопкой "Код".
  • Телепатов на форуме нет! Задавайте чёткий, конкретный и полный вопрос. Указывайте полностью ошибки компилятора и компоновщика.
  • Новое сообщение должно иметь прямое отношение к тематике этого раздела. Флуд, флейм, оффтопик запрещены.
  • Категорически запрещается обсуждение вареза, "кряков", взлома программ и т.д.

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, Любитель.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | С/С++: Кроссплатформенное программирование, Qt/Gtk+/wxWidgets | Следующая тема »


 




[ Время генерации скрипта: 0.0932 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.