как прочитать более 8192 байт с QTcpSocket? - PullRequest
0 голосов
/ 25 сентября 2019

Я отправляю запрос на сервер и получаю ответ, мой код выглядит так:

QString mywindow::SocketCommunication(QString JsonRequest)
{
    QTcpSocket *socket = new QTcpSocket(this);
    QString result;
    socket->connectToHost(SOCKET_IP, SOCKET_PORT);//SOCKET_IP and SOCKET_PORT are defined constants and are correct

    if (socket->waitForConnected(-1) && socket->state() == QAbstractSocket::ConnectedState)
    {

        if (socket->write(JsonRequest.toLatin1()) == -1)
        {

            socket->disconnectFromHost();
            result = "Could not send message";
        }
        else
        {
            socket->flush();


            if (!socket->waitForReadyRead(90000))
            {
                socket->disconnectFromHost();
                result = "tcp con timeout for reading";
            }
            else
            {
                QByteArray JsonResponse = socket->readAll();// the problem is here

                socket->close();

                JsonResponse = JsonResponse.trimmed();
                QString jsonResp = QString::fromStdString(JsonResponse.toStdString());

                result = ParseResponse(jsonResp) // here i parse the response. it works fine and is not important in this question.
            }
        }
    }

    else
    {
        qDebug() << "cannot connect";
        socket->disconnectFromHost();
        result = "Could not Connect to Server";
    }
    return result;
}

Теперь это работает нормально, когда когда-либо ответ от сервера составляет менее 8192 байт.иначе это только читает первые 8192 байта.когда я ставлю socket->error() после прочтения всего, я получаю -1, что является QAbstractSocket :: UnknownSocketError.Есть ли у вас какие-либо идеи, почему это происходит и как я должен это исправить?

ps : я не думаю, что проблема в QAbstractSocket :: DatagramTooLargeError, которая

Датаграмма была больше, чем предел операционной системы (который может составлять 8192 байт).

, потому что я могу отправить более 8192, а другие программы могут обмениваться данными с большимисообщения все в порядке.

Ответы [ 2 ]

0 голосов
/ 25 сентября 2019

Проблема здесь в том, что socket->write() является операцией относительно низкого уровня, которая является частью QIODevice API. не будет разбивать все ваши данные на более мелкие куски размером <8192 байта, чтобы соответствовать требованиям протокола TCP. </p>

Надеемся, вы можете использовать QDataStream для отправки / получения данных безболезненно, бездумать о реализации протокола:

//send data
QDataStream sender(socket);
QByteArray dataWhichMightBeBiggerThan8192Bytes = jsonRequest.toLatin1();
sender << dataWhichMightBeBiggerThan8192Bytes;

Чтобы получить данные:

//connect your socket
QObject::connect(
    socket, &QIODevice::readyRead,
    this, &mywindow::_processIncomingData
);

Затем в вашем классе:

//Is called every time new data is sent to the socket 
void mywindow::_processIncomingData() {

    //prepare to receive data 
    QDataStream receiver(this->_innerSocket); 

    //will loop until the whole waitingBytes of the socket are exhausted 
    while(!receiver.atEnd()) { 

        //start a transaction, so the waitingBytes of the socket can be automatically reset if not all the expected data is there 
        receiver.startTransaction();

        //push waitingBytes into a QByteArray
        QByteArray myJsonAsLatin1;
        receiver >> myJsonAsLatin1;

        //commit : if it failed, means data is missing, so you may keep looping while the client downloads more
        if(auto commitFailed = !receiver.commitTransaction()) continue;

        //commit succeeded, waitingBytes are freed from your QByteArray, you can now process your data
        this->_useMyData(myJsonAsLatin1);

    }

}
0 голосов
/ 25 сентября 2019

Вам может потребоваться установить QAbstractSocket :: setReadBufferSize () в большее значение, если текущее значение слишком мало.Но это внутренний буфер Qt, и по умолчанию он должен быть достаточно большим.Скорее всего, вам нужно установить QAbstractSocket :: ReceiveBufferSizeSocketOption , который является опцией сокета уровня ОС.Посмотрите QAbstractSocket :: socketOption () и QAbstractSocket :: setSocketOption () .

...