crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )


  Ответ в QTcpSocket и QTcpServer
Введите ваше имя
Подтвердите код

Введите в поле код из 6 символов, отображенных в виде изображения. Если вы не можете прочитать код с изображения, нажмите на изображение для генерации нового кода.
 

Опции сообщения
 Включить смайлы?
Иконки сообщения
(Опционально)
                                
                                
  [ Без иконки ]
 


Последние 10 сообщений [ в обратном порядке ]
ssoft Дата 19.12.2011, 7:12
 
Цитата(belirafor @ 19.12.2011, 0:39) *
Тут вообще, кто-нибудь обитает?


Иногда ))).

Проблема , в том, что Вы исользуете waitForReadyRead() - метод, который останавливает основной поток и соотвно графическое отображение таблицы.

Нужно у MainWindow завести slot, например, onSocketRead(), связать его с сокетом

connect( waitForReadyRead(), SIGNAL( readyRead() ), this, SLOT( onSocketRead() ) );


и перенести функционал по считыванию данных туда, и никаких waitForReadyRead().

С множеством клиентов немного посложнее.
Я бы для каждого подключения организовал свой class ServerDelegate : public QObject; в котором бы реализовал логику клиент-серверного взаимодействия со стороны клиента.
belirafor Дата 18.12.2011, 23:39
  Тут вообще, кто-нибудь обитает?
belirafor Дата 13.12.2011, 1:21
  Здравствуйте, уважаемые у частники форума. Пишу контрольную работу "Клиент-сервер". Суть проблемы:
  1. Запускаю сервер
  2. Запускаю клиент
  3. Клиент передает серверу некоторую информацию
  4. Сервер ее обрабатывает и возвращает клиенту результат в поле tableWidget
  5. Нажимаю на клиенте кнопку "Обновить" и поля tableWidget очистились.


Очищаются они потому, что я использую tcpSocket->close() и на сервере и на клиенте после выполнения приема/передачи данных. Если же я не использую tcpSocket->close(), то получается:
  1. запуск сервера
  2. запускаю клиента
  3. Клиент запущен (где-то в памяти), однако окно не появляется у меня на экране.


Подскажите, как сделать так, чтобы клиент не повисал после запуска. В общем как мне обойтись без 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;
}


Заранее, спасибо.
Просмотр темы полностью (откроется в новом окне)
RSS Текстовая версия Сейчас: 20.4.2024, 5:44