Russian Qt Forum
Апрель 19, 2024, 10:11 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Проблема с disconnectFromHost  (Прочитано 7597 раз)
lucky
Гость
« : Февраль 26, 2011, 17:30 »

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

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

но на клиенте вызывается два раза сигнал readyRead. Вот в чем проблема.
Ну и что? Это вполне нормально.
В чем проблема?
Записан
lucky
Гость
« Ответ #3 : Февраль 26, 2011, 18:45 »

Как это нормально? Два раза данные одинаковые приходят.
Записан
BRE
Гость
« Ответ #4 : Февраль 26, 2011, 18:46 »

Два раза данные одинаковые приходят.
А вот это уже не нормально.

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

Записан
lucky
Гость
« Ответ #5 : Февраль 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()));
« Последнее редактирование: Февраль 26, 2011, 18:59 от lucky » Записан
BRE
Гость
« Ответ #6 : Февраль 26, 2011, 19:04 »

Покажи слот slotReadyRead клиента, и на всякий случай метод sendDataToClient сервера.
Записан
BRE
Гость
« Ответ #7 : Февраль 26, 2011, 19:07 »

А ты уверен, что сервер отсылает данные "Data not available" только один раз?
Записан
lucky
Гость
« Ответ #8 : Февраль 26, 2011, 19:09 »

Да проверил сниффером.
Записан
BRE
Гость
« Ответ #9 : Февраль 26, 2011, 19:14 »

Да проверил сниффером.
Покажи слот slotReadyRead клиента, и на всякий случай метод sendDataToClient сервера.
Записан
lucky
Гость
« Ответ #10 : Февраль 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);
}
Записан
BRE
Гость
« Ответ #11 : Февраль 26, 2011, 19:24 »

Как-то не стыкуется:
Код
C++ (Qt)
void FServer::sendDataToClient(qint16 id_msg, QTcpSocket *socket)
{
   ...
}
 
...
sendDataToClient(client, "Data not available");
 
Записан
lucky
Гость
« Ответ #12 : Февраль 26, 2011, 19:30 »

То была другая версия кода, извините, забыл поменять. Вот так: sendDataToClient(100, client); верно. Просто поменял прототип функции. Отправка сообщения и прочее все осталось таким же.
Записан
BRE
Гость
« Ответ #13 : Февраль 26, 2011, 19:45 »

Если клиент отсылает данные серверу - сервер их нормально принимает (ничего не дублируется)?
Если попробовать от сервера к клиенту отправить сразу несколько пакетов, что будет получать клиент (каждый пакет будет дублироваться или только последний)?

Записан
lucky
Гость
« Ответ #14 : Февраль 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;
и цикл убрать тоже правильно будет работать.
Короче не читайте Шлее Улыбающийся, лучше Бланшет.
« Последнее редактирование: Февраль 26, 2011, 21:59 от lucky » Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.072 секунд. Запросов: 20.