Здравствуйте, Уважаемые участники форума. Пишу клиент-серверное приложение. Возникает проблема при поддержке соединения между клиентом и сервером. Нужно, чтобы клиент и сервер постоянно держали соединение. При запуске сервера все хорошо, а при запуске клиента, он повисает в памяти (окно не отображается с данными). При закрытии сервера, окно появляется вместе с данными, которые передал сервер. Если же сделать 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() для нового соединения. Если я правильно понимаю. Заранее спасибо.
|