crossplatform.ru

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

 
Ответить в данную темуНачать новую тему
> QTcpSocket обрезаются файлы
prj
  опции профиля:
сообщение 6.11.2011, 21:32
Сообщение #1


Новичок


Группа: Новичок
Сообщений: 2
Регистрация: 6.11.2011
Пользователь №: 2982

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




Репутация:   0  


Добрый вечер, пишу приложение, которое принимает файлы от другого сервера, и почему-то сохраненные файлы оказываются произвольным образом обрезаны. Например файл 5мб оказывается ~300-400кб, а файл 80кб - 72кб.
Не могу понять в чем дело. Вот кусок кода:
void fclient::get_file(QListWidgetItem* item)
{
    connect_to_s();
    if(tcpSocket.state() != 3)
    {
        qDebug("not connected...");
        return;
    }
    QByteArray str("GET ");
    str += item->text()+"\n";
    tcpSocket.write(str.data());
    tcpSocket.flush();
    QByteArray buf;
    QFile recfile(item->text());
    recfile.open(QIODevice::WriteOnly);
    if(!recfile.exists())
        qDebug("not exists");
    if(recfile.isOpen())
        qDebug("opened");
   int n;
   while(tcpSocket.waitForReadyRead())
   {
        buf = tcpSocket.read(BUFSIZ-1);
        //qDebug(buf.data());
        //qDebug("#");
        qDebug("tcp stat %d", tcpSocket.state());
        recfile.write(buf);
        recfile.flush();
   }
   recfile.close();
   close_conn();
}

void fclient::req_file_list(void)
{
    printf("%d\n", BUFSIZ);
    connect_to_s();
    if(tcpSocket.state() != 3)
        return;

    tcpSocket.write("list\n");
    tcpSocket.flush();    
    QByteArray files, tmp;
    int n=1;
    while(n)
    {
        n = tcpSocket.waitForReadyRead();
        files = tcpSocket.readAll();
        QList<QByteArray> list = files.split('\n');

        while(!list.empty())
        {
            tmp = list.first();
            tmp = tmp.mid(0,tmp.lastIndexOf("\n"));
            list.removeFirst();
            if(tmp.isEmpty())
                continue;
            if(!tmp.contains("endl"))
                   widg->addItem(tmp.data());
                    else
                        {
                            n = 0;
                            break;
                        }
        }
    }
    close_conn();
}
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
ssoft
  опции профиля:
сообщение 7.11.2011, 8:31
Сообщение #2


Участник
**

Группа: Участник
Сообщений: 130
Регистрация: 17.2.2010
Из: Москва
Пользователь №: 1470

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




Репутация:   3  


Мне кажется, что Вы просто не правильно читаете из сокета.
Сокет - это потоковое устройство. Нет гарантии того, что в один пакет, войдет всё, что было послано с другой стороны.
Поэтому необходимо как-то указывать размер передаваемого сообщения, а затем собирать его.

Наример, так

class Reader : public QObject
{
    Q_OBJECT

private:
    QIODevice * io_device;
    QByteArray msg_buffer;
    QByteArray msg_body;
    int read_index;

public:
    Reader ( QIODevice * device, QObject * parent );

private:
    void clean ();

public slots:
    void outputData( QByteArray );

public slots:
    void onReadyRead();

signals:
    void dataInputted( QByteArray );
};


    Reader::Reader ( QIODevice * device, QObject * parent )
        : QObject( parent )
        , io_device( device )
        , index( 0 )
    {
        connect( io_device, SIGNAL( readyRead() ), this, SLOT( onReadyRead() ) );
    }

    void Reader::outputData( QByteArray data )
    {
        QDataStream stream( io_device, QIODevice::WriteOnly );
        stream << data;
    }

    void Reader::clean ()
    {
        msg_buffer.clear();
        msg_body.clear();
        read_index = 0;
    }

    void Reader::onReadyRead()
    {
        msg_buffer += io_device->readAll();
        QDataStream stream( msg_buffer );
        int global_index( 0 );

        while ( !stream.atEnd() )
        {
            if ( msg_body.isEmpty() )
            {
                if ( stream.device()->bytesAvailable() < sizeof( int ) ) //размер сообщения
                    return;
                int count;
                stream >> count;
                msg_body.resize( count );
                global_index += sizeof( int );
            }
            int read_count = stream.readRawData( &( msg_body.data()[ read_index ] ), msg_body.count() - read_index );
            read_index += read_count;
            global_index += read_count;

            if ( msg_body.count() == read_index )
            {
                emit dataInputted( msg_body ); //пришел полный пакет данных
                msg_body.clear();
                read_index = 0;
            }
        }
        msg_buffer.clear();
    }
}
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
prj
  опции профиля:
сообщение 7.11.2011, 17:37
Сообщение #3


Новичок


Группа: Новичок
Сообщений: 2
Регистрация: 6.11.2011
Пользователь №: 2982

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




Репутация:   0  


аааааааааа!!! вчера весь вечер возился, чего только не перепробовал, а щас решил попробовать пренебрегаемой ранее readAll, и все запахало!)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

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


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




RSS Текстовая версия Сейчас: 25.11.2024, 19:11