Como determinar adequadamente que o final de entrada foi alcançado em um QTCPSocket?
-
26-09-2019 - |
Pergunta
Eu tenho o seguinte código que lê de um QTCPSocket:
QString request;
while(pSocket->waitForReadyRead())
{
request.append(pSocket->readAll());
}
O problema com este código é que ele lê toda a entrada e, em seguida, faz uma pausa no final por 30 segundos. (Que é o tempo limite padrão.)
Qual é a maneira correta de evitar o longo tempo de tempo e detectar que o final da entrada foi alcançado? (Uma resposta que evita sinais é preferida porque isso deve estar acontecendo de maneira síncrona em um tópico.)
Solução
A única maneira de ter certeza é quando você recebeu o número exato de bytes que está esperando. Isso geralmente é feito enviando o tamanho dos dados no início do pacote de dados. Leia isso primeiro e depois continue fazendo loop até obter tudo. Uma alternativa é usar um Sentinel, uma série específica de bytes que marcam o final dos dados, mas isso geralmente fica confuso.
Outras dicas
Se você estiver lidando com uma situação como uma resposta HTTP que não contém um comprimento de conteúdo, e você sabe que a outra extremidade fechará a conexão depois que os dados forem enviados, haverá uma solução alternativa.
- Use Socket.SetReadBuffersize para garantir que haja buffer de leitura suficiente para todos os dados que podem ser enviados.
- Ligue para Socket.waitfordisconnected para esperar a extremidade remota para fechar a conexão
- Use soquete.bytesavilable como o comprimento do conteúdo
Isso funciona porque um encerramento da conexão não descarta dados em buffer em um QTCPSocket.