crossplatform.ru

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

 
Ответить в данную темуНачать новую тему
> QDatStream
gpepsi
  опции профиля:
сообщение 17.9.2011, 21:22
Сообщение #1


Студент
*

Группа: Участник
Сообщений: 73
Регистрация: 31.3.2010
Пользователь №: 1582

Спасибо сказали: 0 раз(а)




Репутация:   0  


Есть сокет. Попытался читать из него QDataStream.
На больших данных operator >> возвращает пустые данные.
Есть предположение, что QDataStream читает пока читается, но если данные приходят кусками, то он не успевает все вычитывать.

Есть ли что стандартное, для чтения потока? То есть читать пока читается либо пока не порвется соединение.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
BRE
  опции профиля:
сообщение 17.9.2011, 21:28
Сообщение #2


Профессионал
*****

Группа: Участник
Сообщений: 1112
Регистрация: 6.3.2009
Из: Ростов-на-Дону
Пользователь №: 591

Спасибо сказали: 264 раз(а)




Репутация:   44  


Цитата(gpepsi @ 17.9.2011, 22:22) *
Есть ли что стандартное, для чтения потока? То есть читать пока читается либо пока не порвется соединение.

Ну так QDataStream так и читает.
Расскажи подробней что передается/принимается и как это выглядит в коде.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
gpepsi
  опции профиля:
сообщение 19.9.2011, 5:10
Сообщение #3


Студент
*

Группа: Участник
Сообщений: 73
Регистрация: 31.3.2010
Пользователь №: 1582

Спасибо сказали: 0 раз(а)




Репутация:   0  


Цитата(BRE @ 17.9.2011, 22:28) *
Ну так QDataStream так и читает.

откуда тогда пустые данные

Цитата(BRE @ 17.9.2011, 22:28) *
Расскажи подробней что передается/принимается и как это выглядит в коде.

просто строка длинной более MTU

Сервер в методе incomingConnection
    while(socket.isValid())
    {
        if (socket.waitForReadReady())
        {
            ...
        }
    }
    socket.close();


Клиент
    while(socket.isValid())
    {
        QDataStream stream(&socket);
        stream << QString("...");
        if (socket.waitForReadReady())
        {
            QString data;
            stream >> data;
            ...
        }
    }



З.Ы. Есть еще проблема. Когда сервер рвет соединение, то клиенту сразу приходит сигнал.
А вот если клиент рвет, со серверу пофигу. Вот тестовый код
    #include <QtCore/QCoreApplication>
    #include <QTcpServer>
    #include <QTcpSocket>
    #include <QCoreApplication>
    
    class Client {
    private:
        QTcpSocket m_socket;
    
    public :
        Client () {}
        ~Client() {}
    
        void connect (void)
        {
            m_socket.connectToHost(QHostAddress::LocalHost, 7777);
            if (!m_socket.waitForConnected())
            {
                QT_THROW(m_socket.errorString());
            }
            qDebug("CONNECTED !!!");
        }
    
        void disconnect(void)
        {
            m_socket.close();
            qDebug("DISCONNECTED !!!");
        }
    
        bool isValid(void) const { return m_socket.isValid(); }
    };
    
    class Server : public QTcpServer {
    private:
        Client m_client;
    
        virtual void timerEvent ( QTimerEvent * event )
        {
            static uint counter = 0;
            switch (++counter)
            {
                case 1 : m_client.connect();    break;
                case 2 : m_client.disconnect(); break;
            }
        }
        virtual void incomingConnection( int session )
        {
            QTcpSocket socket(this);
            socket.setSocketDescriptor(session);
    
            while (socket.isValid())
            {
                Q_ASSERT(m_client.isValid());   // Здесь сработает ASSERT, но socket.isValid() :)
                qApp->processEvents();
            }
            socket.close();
        }
    
    public :
        Server ()
        {
            if (!listen(QHostAddress::Any, 7777))
            {
                QT_THROW(QTcpServer::errorString());
            }
            startTimer(100);
        }
        virtual ~Server() {}
    };
    
    int main(int argc, char *argv[])
    {
        QCoreApplication a(argc, argv);
        Server server;
        return a.exec();
    }
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
BRE
  опции профиля:
сообщение 19.9.2011, 7:37
Сообщение #4


Профессионал
*****

Группа: Участник
Сообщений: 1112
Регистрация: 6.3.2009
Из: Ростов-на-Дону
Пользователь №: 591

Спасибо сказали: 264 раз(а)




Репутация:   44  


При серилизации QString вначале записывается ее длина, поэтому QDataStream может определить пришла она полностью или нет. Если она пришла не полностью, то ему не остается ничего другого, кроме возвращения пустой строки при чтении.
Можно пробовать читать из потока и если вернулась пустая строка, то ждать прихода следующего пакета и пробовать читать снова.
Можно писать raw-строки без использования QDataStream и в качестве конца строки использовать "\r\n" (как это делается в http, ftp, ...). Тогда каждую порцию строку можно дописывать в буфер и контролировать маркер конца строки, если он получен, то вырезаем ее из буфера и обрабатываем.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
gpepsi
  опции профиля:
сообщение 19.9.2011, 7:51
Сообщение #5


Студент
*

Группа: Участник
Сообщений: 73
Регистрация: 31.3.2010
Пользователь №: 1582

Спасибо сказали: 0 раз(а)




Репутация:   0  


Цитата(BRE @ 19.9.2011, 8:37) *
Можно пробовать читать из потока и если вернулась пустая строка, то ждать прихода следующего пакета и пробовать читать снова.

ну тогда нужно держать свой буфер накопления, а хотелось возложить это на QDataStream. Ему никак нельзя сказать, чтоб он читал покак не придет все ?

Цитата(BRE @ 19.9.2011, 8:37) *
Можно писать raw-строки без использования QDataStream и в качестве конца строки использовать "\r\n" (как это делается в http, ftp, ...). Тогда каждую порцию строку можно дописывать в буфер и контролировать маркер конца строки, если он получен, то вырезаем ее из буфера и обрабатываем.

ну тоже самое - самому контролировать. Просто я думал, что для TCP это сделано (какой-нибудь QTcpStream)


P.S. А что по поводу закрытия сокетов ?

Сообщение отредактировал gpepsi - 19.9.2011, 8:34
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
BRE
  опции профиля:
сообщение 19.9.2011, 8:28
Сообщение #6


Профессионал
*****

Группа: Участник
Сообщений: 1112
Регистрация: 6.3.2009
Из: Ростов-на-Дону
Пользователь №: 591

Спасибо сказали: 264 раз(а)




Репутация:   44  


Цитата(gpepsi @ 19.9.2011, 8:51) *
ну тогда нужно держать свой буфер накопления, а хотелось возложить это на QDataStream. Ему никак нельзя сказать, чтоб он читал покак не придет все ?

Не буду утверждать, а проверить времени сейчас нет, но скорее всего будет использоваться буфер сокета. Тебе нужно будет дождаться прихода всех пакетов для чтения строки, а пока это не так QDataStream будет возвращать пустую строку.

Цитата(gpepsi @ 19.9.2011, 8:51) *
ну тоже самое - самому контролировать. Просто я думал, что для TCP это сделано (какой-нибудь QTcpStream)

А тут да - нужно будет заводить свой буфер.

Цитата(gpepsi @ 19.9.2011, 8:51) *
P.S. А что по поводу закрытия сокетов ?

А с этим я не понял, что не приходит? Сигнал disconnected?

Сообщение отредактировал BRE - 19.9.2011, 8:28
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
gpepsi
  опции профиля:
сообщение 19.9.2011, 8:34
Сообщение #7


Студент
*

Группа: Участник
Сообщений: 73
Регистрация: 31.3.2010
Пользователь №: 1582

Спасибо сказали: 0 раз(а)




Репутация:   0  


Цитата(BRE @ 19.9.2011, 9:28) *
А с этим я не понял, что не приходит? Сигнал disconnected?


у клиента он проходит. Но сервер не подключен к сигналу, а просто проверяет isValid - вот он проболжает возвращать true после закрытия клиента.

З.Ы. Может тогда унаследоваться от QDataStream и переопределить readRawData & writeRawData, чтоб остались все его возможности
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
BRE
  опции профиля:
сообщение 19.9.2011, 9:52
Сообщение #8


Профессионал
*****

Группа: Участник
Сообщений: 1112
Регистрация: 6.3.2009
Из: Ростов-на-Дону
Пользователь №: 591

Спасибо сказали: 264 раз(а)




Репутация:   44  


Цитата(gpepsi @ 19.9.2011, 9:34) *
у клиента он проходит. Но сервер не подключен к сигналу, а просто проверяет isValid - вот он проболжает возвращать true после закрытия клиента.

А ты состояние проверяй:
SocketState QAbstractSocket::state () const

Цитата(gpepsi @ 19.9.2011, 9:34) *
З.Ы. Может тогда унаследоваться от QDataStream и переопределить readRawData & writeRawData, чтоб остались все его возможности

А что это даст?
Тебе нужен просто цикл добавить и ждать когда придут все данные для чтения хотя-бы одной строки.
Можно в начале отправлять размер пакета и ждать пока придут все данные читая bytesAvailable, а только после этого вычитывать строку из потока.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
gpepsi
  опции профиля:
сообщение 19.9.2011, 10:01
Сообщение #9


Студент
*

Группа: Участник
Сообщений: 73
Регистрация: 31.3.2010
Пользователь №: 1582

Спасибо сказали: 0 раз(а)




Репутация:   0  


Цитата(BRE @ 19.9.2011, 10:52) *
А ты состояние проверяй:
SocketState QAbstractSocket::state () const


ща попробую

Цитата(BRE @ 19.9.2011, 10:52) *
Можно в начале отправлять размер пакета и ждать пока придут все данные читая bytesAvailable, а только после этого вычитывать строку из потока.

а буфера хватит ?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 28.3.2024, 15:00