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

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

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Непонятная проблема с передачей сообщений по tcp между клиентом и сервером  (Прочитано 12638 раз)
Alhin
Гость
« : Октябрь 31, 2009, 11:33 »

Стал реализовывать клиент и сервер обменивающиеся сообщениями по tcp, когда клиент подключается к серверу,  для него запускается отдельный поток. Так вот, если клиент шлет сообщения серверу, то все нормально, но после того как сервер посылает сообщение клиенту, клиентские сообщения до сервера больше не доходят, соответственно код клиента и сервера прилагается.

Код класса потока обрабатывающего прием и отправку сообщений на серверной стороне:
Код:
void ClientThread::readClientMessage(){
    this->__bufferForInputData += this->__clientSocket->readAll();
    forever{
        QDataStream in(&__bufferForInputData, QIODevice::ReadOnly/*this->__clientSocket*/);
        in.setVersion(QDataStream::Qt_4_5);
        if(this->__nextBlockSize == 0){
            if(this->__bufferForInputData.size() < sizeof(qint64)){
                return;
            }
            in >> this->__nextBlockSize;
        }
        if(this->__bufferForInputData.size() < sizeof(qint64) + this->__nextBlockSize){
            return;
        }
        QString message;   
        in >> message;
        this->__nextBlockSize = 0;
        emit gottenMessage(message);
        this->__bufferForInputData.clear();
        return;
    }
}

void ClientThread::sendMessage(QString message){
    QByteArray data;
    QDataStream out(&data, QIODevice::WriteOnly);
    out.setVersion(QDataStream::Qt_4_5);
    out << (qint64)0;
    out << message;
    out.device()->seek(0);
    out << (qint64)(data.size() - sizeof(qint64));

 
    this->__clientSocket->write(data, data.size());
    this->__clientSocket->waitForBytesWritten();
}

На стороне клиента прием и отправка сообщений реализованы точно также:
Код:
void TcpClient::sendMessage(QString message){
    if(this->__tcpSocket->state() != QAbstractSocket::ConnectedState){
        return;
    }
    QByteArray data;
    QDataStream out(&data, QIODevice::WriteOnly);
    out.setVersion(QDataStream::Qt_4_5);
    out << (qint64)0;
    out << message;
    out.device()->seek(0);
    out << (qint64)(data.size() - sizeof(qint64));


    this->__tcpSocket->write(data, data.size());
    this->__tcpSocket->waitForBytesWritten();
}

void TcpClient::readServerMessage(){
    this->__bufferForInputData += this->__tcpSocket->readAll();
    forever{
        QString message;
        QDataStream in(&__bufferForInputData, QIODevice::ReadOnly/*this->__tcpSocket*/);
        if(this->__nextBlockSize == 0){
            if(this->__bufferForInputData.size() < sizeof(qint64)){
                return;
            }
            in >> this->__nextBlockSize;
        }
        if(this->__bufferForInputData.size() < sizeof(qint64) + this->__nextBlockSize){
            return;
        }
        in >> message;
        this->__nextBlockSize = 0;
        emit gottenMessage(message);
        this->__bufferForInputData.clear();
        return;
    }
}

Есть идеи как решить эту проблему?
Заранее спасибо!
Записан
BRE
Гость
« Ответ #1 : Октябрь 31, 2009, 11:51 »

Смущает следующий кусок кода в обоих слотах чтения:
Код
C++ (Qt)
void ClientThread::readClientMessage(){
...
       if(this->__bufferForInputData.size() < sizeof(qint64) + this->__nextBlockSize){
           return;
       }
...
}
 
Размер блока (sizeof(qint64)) ты уже прочитал.

Попробуй так:
Код
C++ (Qt)
void ClientThread::readClientMessage(){
...
       if(this->__bufferForInputData.size() < this->__nextBlockSize){
           return;
       }
...
}
 
Записан
Alhin
Гость
« Ответ #2 : Октябрь 31, 2009, 12:02 »

Исправил, но проблема все равно осталась.
Записан
BRE
Гость
« Ответ #3 : Октябрь 31, 2009, 12:08 »

Исправил, но проблема все равно осталась.
И в TcpClient::readServerMessage() исправил?

Вопрос по протоколу:
* Клиент подключается к серверу
* Клиент посылает сообщение серверу (нормально доходит?)
* Сервер посылает сообщение клиенту (нормально доходит?)
* Клиент посылает сообщение серверу (сервер его не получает?)
Записан
Alhin
Гость
« Ответ #4 : Октябрь 31, 2009, 20:10 »

Да, там тоже исправил.
Клиент подключается к серверу - да.
Клиент посылает сообщение серверу - все доходит без проблем.
Сервер посылает сообщение клиенту - тоже все доходит и проблем не наблюдается.
(*) Клиент посылает сообщение серверу - здесь уже сервер не получает сообщений.
Причем заметил такую интересную вещь, что после того как серверу не дошло сообщение от клиента
переслать от сервера клиенту сообщение, то серверу приходит отправленное в случае (*) сообщение(
причем только первое из отправленных). Если же этого не делать, то сообщения не поступают.

Причем, если закоментить в коде клиента и сервера:
Код:
this->__tcpSocket->waitForBytesWritten();
то такого интересного эффекта не наблюдается.

Решил проверить свой код на debian - все работает без проблем.
В голове не укладывается в чем тут может быть дело...
Записан
BRE
Гость
« Ответ #5 : Октябрь 31, 2009, 20:15 »

Причем, если закоментить в коде клиента и сервера:
Код:
this->__tcpSocket->waitForBytesWritten();
то такого интересного эффекта не наблюдается.
А для чего ты вызываешь эту функцию?
Записан
Alhin
Гость
« Ответ #6 : Октябрь 31, 2009, 20:29 »

На самом деле первоначальный вариант был без нее,
дописал ее из соображения "авось поможет".
Записан
BRE
Гость
« Ответ #7 : Октябрь 31, 2009, 20:30 »

Так сейчас под linux все работает, а под вендой нет?
Записан
Alhin
Гость
« Ответ #8 : Октябрь 31, 2009, 20:31 »

Да, именно так.
Записан
BRE
Гость
« Ответ #9 : Октябрь 31, 2009, 20:36 »

А попробуй вместо
Код
C++ (Qt)
this->__tcpSocket->waitForBytesWritten();
 
поставить
Код
C++ (Qt)
this->__tcpSocket->flush();
 
Записан
Alhin
Гость
« Ответ #10 : Октябрь 31, 2009, 20:39 »

Пробовал - не помогает.
Записан
BRE
Гость
« Ответ #11 : Октябрь 31, 2009, 20:46 »

Пробовал - не помогает.
Хм, странно... С вендой помочь не смогу, не пользуюсь, но если захочешь выложи архив с проектом, я его под linux посмотрю, кто-то может под вендой попробует.
Записан
Alhin
Гость
« Ответ #12 : Октябрь 31, 2009, 21:00 »

Проект смогу выложить только утром в понедельник.
Записан
Alhin
Гость
« Ответ #13 : Ноябрь 02, 2009, 10:08 »

Вот обещанный архив с исходниками, соответственно исходники клиента в папке Client, а сервера - Server.
Записан
BRE
Гость
« Ответ #14 : Ноябрь 02, 2009, 12:55 »

Вот обещанный архив с исходниками, соответственно исходники клиента в папке Client, а сервера - Server.
Лучше и pro файлы в архив класть.  Подмигивающий

Сейчас нет времени подробно разбираться... Посмотри на сообщения, которые выдаются в консоль при работе сервера.

Если объект создается в конструкторе Thread, то он создается и принадлежит контексту того потока из которой вызывается конструктор (в твоем случае это главный поток), а используешь ты его в контексте дочернего потока (в методе run). Нужно или переносить объект в контекст дочерней нити (см QObject::moveToThread), или непосредственно создавать объект в контексте дочерней нити (т.е. в методе run).
« Последнее редактирование: Ноябрь 02, 2009, 12:58 от BRE » Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


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