Russian Qt Forum

Qt => Вопросы новичков => Тема начата: lucky от Февраль 26, 2011, 17:30



Название: Проблема с disconnectFromHost
Отправлено: lucky от Февраль 26, 2011, 17:30
Возникла следующая проблема. Приходят мне данные от клиента на сервер. Я их обрабатываю, и если они некорректные я отправляю сообщение клиенту об ошибке и закрываю соединение:
Код:
        sendDataToClient(client, "Data not available");
        client->disconnectFromHost();
На сервере все происходит на ура, а вот на клиенте почему то два раза вызывается сигнал readyRead. Помогите пожалуйста.


Название: Re: Проблема с disconnectFromHost
Отправлено: lucky от Февраль 26, 2011, 18:28
Только что проверил, проблема не в
Код:
client->disconnectFromHost();
. Проверил сниффером данные отправляются один раз методом
Код:
sendDataToClient(client, "Data not available");
, но на клиенте вызывается два раза сигнал readyRead. Вот в чем проблема.


Название: Re: Проблема с disconnectFromHost
Отправлено: BRE от Февраль 26, 2011, 18:32
но на клиенте вызывается два раза сигнал readyRead. Вот в чем проблема.
Ну и что? Это вполне нормально.
В чем проблема?


Название: Re: Проблема с disconnectFromHost
Отправлено: lucky от Февраль 26, 2011, 18:45
Как это нормально? Два раза данные одинаковые приходят.


Название: Re: Проблема с disconnectFromHost
Отправлено: BRE от Февраль 26, 2011, 18:46
Два раза данные одинаковые приходят.
А вот это уже не нормально.

Покажи как отсылаешь/принимаешь. Как подключаешь сигнал и слот (может ты его дважды подключаешь).
Нужно больше информации.



Название: Re: Проблема с disconnectFromHost
Отправлено: lucky от Февраль 26, 2011, 18:57
Вот слот сервера, который срабатывает когда приходит новое подключение:
Код:
void FServer::clientConnected()
{
    while (hasPendingConnections())
    {
        QTcpSocket *client = nextPendingConnection();
        connect(client, SIGNAL(readyRead()), this, SLOT(slotReadDataClient()));
        connect(client, SIGNAL(disconnected()), this, SLOT(clientDisconnected()));
        arrayConnections.append(client);

        qDebug() << "Connect: " << client->peerAddress();
    }
}

В нем назначаем слоты для сокета-клиента + добавляем его в список сокетов. Теперь подключается клиент и отправляет определенные данные я их принимаю и если они некорректны хочу обрубить подключение, но перед этим отправляю причину ему.
Слот на сервере для принятия данных:
Код:
void FServer::slotReadDataClient()
{
    QTcpSocket *client = qobject_cast<QTcpSocket *>(sender());
    QDataStream in(client);
    in.setVersion(QDataStream::Qt_4_7);

    while(true)
    {
        if(!blockSize)
        {
            if(client->bytesAvailable() < sizeof(quint16))
                break;

            in >> blockSize;
        }

        if(client->bytesAvailable() < blockSize)
            break;

        in >> id_msg;

        //Обработка мной данных, если они некорректны отправляю отказ и обрубаю соединение.
        sendDataToClient(client, "Data not available");
        client->disconnectFromHost();

        blockSize = 0;
    }
}

На клиенте вызывается два раза сигнал readyRead.
Код на клиенте:
   
Код:
socket = new QTcpSocket(this);

    socket->connectToHost("127.0.0.1", 7777);
    connect(socket, SIGNAL(connected()), this, SLOT(slotConnected()));
    connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(slotError(QAbstractSocket::SocketError)));
    connect(socket, SIGNAL(readyRead()), this, SLOT(slotReadyRead()));


Название: Re: Проблема с disconnectFromHost
Отправлено: BRE от Февраль 26, 2011, 19:04
Покажи слот slotReadyRead клиента, и на всякий случай метод sendDataToClient сервера.


Название: Re: Проблема с disconnectFromHost
Отправлено: BRE от Февраль 26, 2011, 19:07
А ты уверен, что сервер отсылает данные "Data not available" только один раз?


Название: Re: Проблема с disconnectFromHost
Отправлено: lucky от Февраль 26, 2011, 19:09
Да проверил сниффером.


Название: Re: Проблема с disconnectFromHost
Отправлено: BRE от Февраль 26, 2011, 19:14
Да проверил сниффером.
Покажи слот slotReadyRead клиента, и на всякий случай метод sendDataToClient сервера.


Название: Re: Проблема с disconnectFromHost
Отправлено: lucky от Февраль 26, 2011, 19:16
Код:
void MainWindow::slotReadyRead()
{
    QDataStream in(socket);
    in.setVersion(QDataStream::Qt_4_7);
    while (true) {
        if (!blockSize) {
            if (socket->bytesAvailable() < sizeof(quint16))
                break;

            in >> blockSize;
        }

        if (socket->bytesAvailable() < blockSize)
            break;

        in >> id_msg;

        //Тут разбор сообщения, нечего "военного"

        blockSize = 0;
    }
}


Код:
void FServer::sendDataToClient(qint16 id_msg, QTcpSocket *socket)
{
    QByteArray block;
    QDataStream out(&block, QIODevice::WriteOnly);
    out.setVersion(QDataStream::Qt_4_7);

    switch(id_msg)
    {
        case 100:
        {
         //Формируем сообщение
        } break;
    }

    out.device()->seek(0);
    out << quint16(block.size() - sizeof(quint16));


    socket->write(block);
}


Название: Re: Проблема с disconnectFromHost
Отправлено: BRE от Февраль 26, 2011, 19:24
Как-то не стыкуется:
Код
C++ (Qt)
void FServer::sendDataToClient(qint16 id_msg, QTcpSocket *socket)
{
   ...
}
 
...
sendDataToClient(client, "Data not available");
 


Название: Re: Проблема с disconnectFromHost
Отправлено: lucky от Февраль 26, 2011, 19:30
То была другая версия кода, извините, забыл поменять. Вот так: sendDataToClient(100, client); верно. Просто поменял прототип функции. Отправка сообщения и прочее все осталось таким же.


Название: Re: Проблема с disconnectFromHost
Отправлено: BRE от Февраль 26, 2011, 19:45
Если клиент отсылает данные серверу - сервер их нормально принимает (ничего не дублируется)?
Если попробовать от сервера к клиенту отправить сразу несколько пакетов, что будет получать клиент (каждый пакет будет дублироваться или только последний)?



Название: Re: Проблема с disconnectFromHost
Отправлено: lucky от Февраль 26, 2011, 21:26
BRE спасибо, что откликнулись. Проблема была решена. В слоте slotReadDataClient на сервере при разборе сообщения, в цикле, сделал так:
Код:
    while(true)
    {
        if(!m_blockSize)
        {
            if(client->bytesAvailable() < sizeof(quint16))
                break;

            in >> m_blockSize;
        }

        if(client->bytesAvailable() < m_blockSize)
            break;

        if(!m_blockSize)
            break;

        //Разбор сообщения

        m_blockSize = 0;
    }


Код:
        if(!m_blockSize)
            break;

Если без этого
Код:
 if(!m_blockSize)
            break;
и цикл убрать тоже правильно будет работать.
Короче не читайте Шлее :), лучше Бланшет.