Russian Qt Forum

Qt => Работа с сетью => Тема начата: Fregloin от Январь 10, 2012, 16:40



Название: Потоковая прием/передача данных в JSON (через QTcpClient)
Отправлено: Fregloin от Январь 10, 2012, 16:40
Как грамотно организовать потоковую передачу данных в формате JSON сокетами Qt? (не Http, SSL...).
Размер каждого JSON кадра порядка 30-50Кб. Данные приходят от сервера с частотой 4 раза в секунду.
Раньше передавали кадры бинарных данных (по сути слепки памяти) и размеры кадров были всегда одними и теми же.
Но такой подход очень не гибкий, решили передавать данные в тексте, в угоду универсальности передаваеммых данных.
Данные сервер будет передавать без сериализации QDataStream (так как пишется не на Qt,а на boost).


Название: Re: Потоковая прием/передача данных в JSON (через QTcpClient)
Отправлено: asvil от Январь 10, 2012, 16:52
парсить json, не?


Название: Re: Потоковая прием/передача данных в JSON (через QTcpClient)
Отправлено: fuCtor от Январь 10, 2012, 16:54
Посмотри на это решение:
http://qjson.sourceforge.net/
Умеет цепляться к QIODevice, но как себя будет вести на потоковых устройствах не знаю. Есть еще момент с разделением пакетов, тоже придется как-то решить, либо дожидаться прихода пакета целиком (по доп заголовку) и после уже разбирать.


Название: Re: Потоковая прием/передача данных в JSON (через QTcpClient)
Отправлено: Fregloin от Январь 10, 2012, 17:42
вот мой код (еще не опробован, так как сервер не готов)
Код:
void     QGenericArmClient::readyRead()
{
    int bytesAvail = fsocket->bytesAvailable();

#ifdef  JSON_FORMAT
    if(bytesAvail<=0) return;
    QByteArray  packetData = fsocket->readAll();

    if(!packetData.isEmpty())
    {
        int terminatorIndex;
        int prevTerminatorIndex = 0;
        int dataSize = packetData.size();

        terminatorIndex = packetData.indexOf('\0',prevTerminatorIndex); //ищем первый терминатор в пакете
        if(terminatorIndex<0)   //если нет терминатора, копируем целиком
        {
            fcurrentData.append(packetData);
        }
        else
        {
            do  //проходимся по кадру
            {
                fcurrentData.append(packetData.mid(prevTerminatorIndex,(terminatorIndex-prevTerminatorIndex))); //копируем часть до терминатора
                emit jsonFrameReceived(QString(fcurrentData));  //сигналим об очередной строке с json
                fcurrentData.clear();                           //стираем временный буфер
                prevTerminatorIndex = terminatorIndex+1;        //сдвигаем указатель, с которого будем искать следующий терминатор
            }
            while(((terminatorIndex = packetData.indexOf('\0',prevTerminatorIndex))<0) || (prevTerminatorIndex>dataSize));  //до тех пор, пока больше нет терминаторов
            if(prevTerminatorIndex<dataSize)
            {
                fcurrentData.append(packetData.mid(prevTerminatorIndex,(dataSize-prevTerminatorIndex)));//копируем остаток
            }
        }
    }
#endif
}

планируется гонять текст json,завершающийся нулём (признак окончания пакета).