Как отправлять данные с сервера на клиент как QByteArray/QDataStream

В образце Qt для сервера состояний QString отправляется методом sendFortune(). Поэтому одна QString выбирается из QStringList fortunes:

QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt(quint16)0);
out << (quint16)0;
out << fortunes.at(qrand() % fortunes.size());
out.device()->seek(0);
out << (quint16)(block.size() - sizeof(quint16));

QTcpSocket *clientConnection = tcpServer->nextPendingConnection();
clientConnection->write(block);

Можно ли также отправить другой тип данных, например файлы, изображения или несколько строк? Или можно просто отправить одну строку?

Мой второй вопрос: в чем преимущество отправки данных как QByteArry и почему я должен определить (quint16), настроив QDataStream?


person 3ef9g    schedule 01.10.2014    source источник
comment
Чтобы быть очень простым, связь клиент/сервер использует такие протоколы, как TCP. Этот протокол инкапсулирует ваше сообщение для достижения пункта назначения. Сообщения — это байты. Байты могут быть изображениями, строками, файлами, чем угодно, потому что все является байтами. Что касается вопроса quint16, вы должны понимать, что вам нужно определить свои правила для отправки/получения сообщения, иначе вы никогда не узнаете, когда сообщение начинается и когда оно заканчивается.   -  person Martin    schedule 01.10.2014
comment
Есть ли примеры? Потому что это факт - я хотел бы понять это - но без некоторых упражнений это трудно понять. ... Какой размер я должен использовать для строк, какой размер для изображений или текстовых файлов ... Я понятия не имею ... Некоторая помощь была бы отличной   -  person 3ef9g    schedule 05.10.2014
comment
Вам не нужно беспокоиться об этих размерах. Имейте в виду, что tcp comm — это потоковая связь. Таким образом, вы получаете 0101101010101... когда угодно вовремя. Вы должны определить свои правила (или использовать некоторые прикладные протоколы, такие как http), чтобы знать начало и конец сообщения. Допустим, вы хотите отправить строку приветствия. Сначала вы пишете 0x00 0x00, чтобы знать, что это начало сообщения. Потом пишешь привет. А потом пишешь размер своей строки 0x05. Таким образом, вы отправляете 00 00 68 65 6c 6c 6f 00 05 на свой сокет.   -  person Martin    schedule 06.10.2014
comment
С другой стороны, вы получите 00 00 68 65 6c 6c 6f 00 05. Сначала вы берете 2 последних байта 00 05, вычисляя, что вы ожидаете сообщение длиной 5 байт. Итак, вы читаете с 3-го байта, потому что первые два равны 00 00, и у вас есть 68 65 6c 6c 6f. Это сообщение длиной 5, так что это действительное сообщение. Итак, у вас есть приветственная строка. Зачем такая сложная вещь для этого? Потому что с tcp вы общаетесь с пакетами, и вы не знаете, сколько пакетов вам нужно для передачи ваших данных и, очевидно, хорошо ли вы получаете все свои пакеты.   -  person Martin    schedule 06.10.2014


Ответы (2)


Вы не отправляете данные как QDataStream, QDataStream — это класс, который олицетворяет поток, способ передачи данных, например провод. QByteArray представляет собой хранилище для ваших данных. Итак, вы можете отправлять данные как QByteArray. Вы можете попробовать функцию-член QTcpSocket под названием «int write (QByteArray)», как в приведенном вами примере. Просто возьмите изображение, файл, любые другие данные и преобразуйте их в QByteArray. Здесь вам понадобится QDataStream. Привяжите поток к bytearray следующим образом.

QByteArray dat; QDataStream out(&dat, QIODevice::WriteOnly);

и использовать для заполнения дат.

out << myImage << myImage2;

Когда вы закончили заполнять QByteArray, отправьте его:

mySocket.write(dat);

не забудьте проверить возвращаемое значение. Читайте документы и у вас все получится.

person Asalle    schedule 15.06.2015

Чтобы узнать, прочитали ли вы все данные, отправленные другой стороной сокета, я использую функцию commitTransaction() из QDataStream:

Client::Client()
{
    ....
    connect(tcpSocket, &QIODevice::readyRead, this, &Client::readData);
    ....
}

void Client::readData()
{
    in.startTransaction();

    QString data;
    in >> data;

    if (!in.commitTransaction())
    {
        qDebug() << TAG << "incomplete: " << data;
        // readyRead will be called again when there is more data
        return;
    }

    // data is complete, do something with it
    ....
person Boy    schedule 11.09.2017