¿Cómo asegurarse de que las señales readyRead () de QTcpSocket no se puedan perder?

Cuando usasQTcpSocket Para recibir datos, la señal a utilizar esreadyRead(), lo que señala que hay nuevos datos disponibles. Sin embargo, cuando se encuentra en la implementación de la ranura correspondiente para leer los datos, no hay datos adicionales.readyRead() será emitido. Esto puede tener sentido, ya que usted está en la función, donde está leyendo todos los datos disponibles.

Descripción del problema

Sin embargo, supongamos la siguiente implementación de esta ranura:

void readSocketData()
{
    datacounter += socket->readAll().length();
    qDebug() << datacounter;
}

¿Qué pasa si algunos datos llegan después de llamarreadAll() ¿Pero antes de dejar la ranura? ¿Qué sucede si este fue el último paquete de datos enviado por la otra aplicación (o al menos el último por algún tiempo)? No se emitirá ninguna señal adicional, por lo que debe asegurarse de leer todos los datos usted mismo.

Una forma de minimizar el problema (pero no evitarlo totalmente)

Por supuesto que podemos modificar la ranura así:

void readSocketData()
{
    while(socket->bytesAvailable())
        datacounter += socket->readAll().length();
    qDebug() << datacounter;
}

Sin embargo, no hemos resuelto el problema. Todavía es posible que los datos lleguen justo después de lasocket->bytesAvailable()-check (e incluso colocar el / otro check en el final absoluto de la función no resuelve esto).

Asegurándose de poder reproducir el problema.

Como este problema, por supuesto, ocurre muy raramente, me atengo a la primera implementación de la ranura, e incluso agrego un tiempo de espera artificial, para asegurarme de que ocurra el problema:

void readSocketData()
{
    datacounter += socket->readAll().length();
    qDebug() << datacounter;

    // wait, to make sure that some data arrived
    QEventLoop loop;
    QTimer::singleShot(1000, &loop, SLOT(quit()));
    loop.exec();
}

Luego dejo que otra aplicación envíe 100,000 bytes de datos. Esto es lo que pasa:

¡Nueva conexión!
32768 (o 16K o 48K)

La primera parte del mensaje se lee, pero el final ya no se lee, comoreadyRead() no será llamado de nuevo

Mi pregunta es: ¿cuál es la mejor manera de estar seguro, este problema nunca ocurre?

Solución posible

Una solución que se me ocurrió es volver a llamar a la misma ranura al final, y para verificar al principio de la ranura, si hay más datos para leer:

void readSocketData(bool selfCall) // default parameter selfCall=false in .h
{
    if (selfCall && !socket->bytesAvailable())
        return;

    datacounter += socket->readAll().length();
    qDebug() << datacounter;

    QEventLoop loop;
    QTimer::singleShot(1000, &loop, SLOT(quit()));
    loop.exec();

    QTimer::singleShot(0, this, SLOT(readSocketDataSelfCall()));
}

void readSocketDataSelfCall()
{
    readSocketData(true);
}

Como no llamo a la ranura directamente, pero usoQTimer::singleShot(), Supongo que elQTcpSocket No puedo saber que estoy llamando a la ranura de nuevo, por lo que el problema quereadyRead() no se emite ya no puede suceder.

La razón por la que he incluido el parámetrobool selfCall es que la ranura que se llama por elQTcpSocket no se le permite salir antes, de lo contrario, puede volver a ocurrir el mismo problema, los datos llegan exactamente en el momento equivocado yreadyRead() no se emite.

¿Es esta realmente la mejor solución para resolver mi problema? ¿Es la existencia de este problema un error de diseño en Qt o me estoy perdiendo algo?

Respuestas a la pregunta(6)

Su respuesta a la pregunta