Russian Qt Forum

Qt => Работа с сетью => Тема начата: Edynchik от Декабрь 24, 2010, 16:32



Название: Передача сообщений между клиентом и сервером
Отправлено: Edynchik от Декабрь 24, 2010, 16:32
Помогите разобраться, для примера клиент-серверного приложения использовал FortuneClient и FortuneServer. Там после передачи сообщения используется disconnectFromHost. То есть соединение клиента с сервером разрывается, и собственно вопрос: Возможно ли обмен сообщениями между клиентом и сервером и обратно,без постоянного разрыва соединения? И собственно как это сделать?
Клиент:
Код:
void MainWindow::readFortune()
{
//! [9]
    QDataStream in(tcpSocket);
    in.setVersion(QDataStream::Qt_4_7);

    if (blockSize == 0) {
        if (tcpSocket->bytesAvailable() < (int)sizeof(quint16))
            return;
//! [8]

//! [10]
        in >> blockSize;
    }

    if (tcpSocket->bytesAvailable() < blockSize)
        return;
//! [10] //! [11]

    QString nextFortune;
    in >> nextFortune;

    if (nextFortune == currentFortune) {
        QTimer::singleShot(0, this, SLOT(requestNewFortune()));
        return;
    }
//! [11]

//! [12]
    currentFortune = nextFortune;
//! [9]
    //ui->lineEdit->setText(currentFortune);
    ui->textEdit->setText(currentFortune);
    ui->pushButton->setEnabled(true);
}
Сервер:
Код:
void MainWindow::on_Button1_clicked()
{
        m_ptcpServer = new QTcpServer(this);
        if (!m_ptcpServer->listen(QHostAddress(ui->lineEdit_2->text()) , ui->lineEdit_3->text().toInt()))
            {
            ui->label_3->setText("Server is not working " + m_ptcpServer->errorString());
            m_ptcpServer->close();
            return;
            }
        ui->label_3->setText("Server is working");
        connect(m_ptcpServer, SIGNAL(newConnection()),this,SLOT(slotNewConnection()));

}

void MainWindow::slotNewConnection()
{

        //QTcpSocket* pClientSocket = m_ptcpServer->nextPendingConnection();
        pClientSocket = new QTcpSocket(this);
        pClientSocket = m_ptcpServer->nextPendingConnection();
        connect(pClientSocket, SIGNAL(disconnected()),
                        pClientSocket, SLOT(deleteLater())
                   );
        connect(pClientSocket, SIGNAL(readyRead()),
                        this,   SLOT(slotReadClient())
                   );
        ui->label_3->setText("Server Response: Connected!");
        //sendToClient(pClientSocket, "Server Response: Connected!");
        //sendMessage("Server Response: Connected!");


}


void MainWindow::on_pushButton_2_clicked()
{
    //m_ptcpServer = new QTcpServer(this);
    //FileServer SERVER1("C:/",this);
    //QTcpSocket* pClientSocket = (QTcpSocket*)sender();
    sendMessage(ui->lineEdit->text());
    //SERVER1.incomingConnection(m_ptcpServer->socketDescriptor());
    ;
}


void MainWindow::sendMessage(QString MESSAGE)
{

    QByteArray block;
    QDataStream out(&block, QIODevice::WriteOnly);
    out.setVersion(QDataStream::Qt_4_7);

    out << (quint16)0;
    //out << fortunes.at(qrand() % fortunes.size());
    //out << ui->lineEdit->text();
    out << MESSAGE;
    out.device()->seek(0);
    out << (quint16)(block.size() - sizeof(quint16));


    /*QTcpSocket *pClientSocket = m_ptcpServer->nextPendingConnection();//tcpServer->nextPendingConnection();
    connect(pClientSocket, SIGNAL(disconnected()),
            pClientSocket, SLOT(deleteLater()));*/

    pClientSocket->write(block);
    pClientSocket->disconnectFromHost();
    //clientConnection->write(block);
    //clientConnection->disconnectFromHost();

}


Название: Re: Передача сообщений между клиентом и сервером
Отправлено: kuzulis от Декабрь 24, 2010, 16:36
Цитировать
Возможно ли обмен сообщениями между клиентом и сервером и обратно,без постоянного разрыва соединения?
Да, возможен.
Цитировать
И собственно как это сделать?
Не разрывать соединение.


Название: Re: Передача сообщений между клиентом и сервером
Отправлено: Edynchik от Декабрь 24, 2010, 16:48
Не разрывать соединение.
Да это было наиболее очевидное решение, убрав disconnectFromHost,при отправке первого сообщения от сервера к клиенту все нормально,а вот при отправке второго сообщения оно приходит пустым, т.е. в строчке in >> nextFortune; пусто (""). И собственно на этом все заканчивается.


Название: Re: Передача сообщений между клиентом и сервером
Отправлено: brankovic от Декабрь 24, 2010, 16:49
Разрыв соединения гарантирует, что данные отправлены. Если не разрывать, то надо вызывать QSocket::flush после каждого сообщения.


Название: Re: Передача сообщений между клиентом и сервером
Отправлено: Edynchik от Декабрь 24, 2010, 17:06
Разрыв соединения гарантирует, что данные отправлены. Если не разрывать, то надо вызывать QSocket::flush после каждого сообщения.
Добавление flush после отправки сообщения не помогла.
Код:
pClientSocket->write(block);
pClientSocket->flush();
но отметиласть интересная особенность: первое сообщение принимается нормально,второе и третье нет, а четверное-нормально, и так далее через два...


Название: Re: Передача сообщений между клиентом и сервером
Отправлено: JamS007 от Декабрь 24, 2010, 17:40
Нет времени разбираться с твоим кодом, но когда-то я тоже наткнулся на похожую проблему. В моем случае виной всему было, то, что я после принятого сообщения blockSize не присваивал 0, из-за чего нарушался алгоритм приема следующего сообщения. в твоем коде я этого тоже не вижу.

И еще, иногда бывает, что по ошибке ставят на сервере quint16 blockSize а на клиенте quint32 blockSize, или наоборот. При первом сообщении все тоже будет нормально, а с последующими будет беда.


Название: Re: Передача сообщений между клиентом и серв&
Отправлено: brankovic от Декабрь 25, 2010, 11:48
block_size не присваивается 0. И вообще это пример с дисконнектом, выкладывать надо ваш, который не работает.


Название: Re: Передача сообщений между клиентом и сервером
Отправлено: Edynchik от Декабрь 25, 2010, 14:21
4 brankovic
а где именно надо присваивать block_size=0?
Сосбственно вот два проекта,клиента и сервера...


Название: Re: Передача сообщений между клиентом и сервером
Отправлено: Edynchik от Декабрь 27, 2010, 09:29
А ларчик то просто открывался: достаточтно убрать out << (quint16)(block.size() - sizeof(quint16)); и поставаить pClientSocket->flush();и все работает)))