Здравствуйте, уважаемые у частники форума. Пишу контрольную работу "Клиент-сервер". Суть проблемы:
- Запускаю сервер
- Запускаю клиент
- Клиент передает серверу некоторую информацию
- Сервер ее обрабатывает и возвращает клиенту результат в поле tableWidget
- Нажимаю на клиенте кнопку "Обновить" и поля tableWidget очистились.
Очищаются они потому, что я использую tcpSocket->close() и на сервере и на клиенте после выполнения приема/передачи данных. Если же я
не использую tcpSocket->close(), то получается:
- запуск сервера
- запускаю клиента
- Клиент запущен (где-то в памяти), однако окно не появляется у меня на экране.
Подскажите, как сделать так, чтобы клиент не повисал после запуска. В общем как мне обойтись без tcpSocket->close() после передачи данных. Поскольку мне нужно выводить информацию о подключаемых клиентах на сервере. А если буду каждый раз инициировать соединение со стороны клиента, тогда будет путаница.
Скажу сразу - я плохо разбираюсь в программировании, в силу того что не работаю по специальности (а с сокетами вообще никогда не имел дела). Посмотреть примеры из Qt creator не предлагайте. Смотрел много раз Threaded Fortune Server Example и Client Example.
Ниже привожу код клиента и сервера, а так же ссылку на Cyberforum, где расположена
моя тема/*Клиент*/
//mainwindow.cpp
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);
tcpSocket->close();
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));}
fncConnect(); //После закрытия сокета инициируем соединение по новой
}
void MainWindow::fncConnect()
{
tcpSocket = new QTcpSocket(this);
tcpSocket->connectToHost("localhost", 3333);
}
/*Сервер*/
#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(AcceptConn()));
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::AcceptConn()
{
// NewIncConn();
tcpSocket = tcpServer->nextPendingConnection();
connect(tcpSocket, SIGNAL(readyRead()), SLOT(IncKey()));
}
void DlgInfo::IncKey()
{
QByteArray Key = tcpSocket->readAll();
if(Key == "qryJrnl_SELECT")
{
JrnlRefresh();
ui->txtbrsr_Info->append(tr("Обновили данные окна"));
return;
}
}
void DlgInfo::JrnlRefresh()
{
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;
}
Заранее, спасибо.