2015-02-04 3 views
0

Я пишу функцию для связи с тестовым сервером, который я не писал. Я посылаю команду и должен немедленно захватить многострочный ответ, прежде чем делать что-либо еще. Конечно, я бы не хотел блокировать весь пользовательский интерфейс, что не должно быть проблемой, так как при отправке команды ответ составляет всего несколько номинальных мс.Невозможно получить многострочные данные из qtcpsocket qt

Это, как говорится, это то, что я придумал:

QByteArray MainWindow::ask(const QByteArray &cmd) //blocking function. Add  to thread while in use? 
{ 
     this->consoleWindow->put_data_in_console(cmd); 
     this->socket->write(cmd + "\r\n"); 

     QByteArray resBuffer; 
     socket->waitForReadyRead(); 

     while(socket->bytesAvailable > 0) 
     { 
      resBuffer.append(socket->readAll()); 
     } 
     return resBuffer; 

}

Но я только смог захватить первую линию моего ответа четыре строки.

Заранее благодарен!

+1

Переходя от [аналогичного вопроса, где вы спрашивали меня о помощи здесь] (http://stackoverflow.com/questions/14189015), я должен сказать то же самое, что и там: вам нужно иметь какой-то разделитель или что-либо, что говорит вам на стороне получателя при завершении ответа. Какой протокол использует сервер? – leemes

+0

Это TCP, и он исходит из тестовой машины (так что я не знаю, какой формат пакетов в точности). Я намерен задать серверу вопрос (в функции запроса) и сразу вернуть результат, который будет состоять из нескольких переменных строк ascii-текста, где каждая строка заканчивается на «\ r \ n» или «\ n \ r». Я буду знать, сколько строк ответ будет.Я успешно выполнил асинхронную запись каждой строки, поскольку каждый из них отправляется сервером на каждом сигнале readyRead(), но мне нужно зафиксировать все строки, следующие за моей командой вопроса, в функции «ask», а не в слоте onReadyRead(). Спасибо – Rachael

+0

Почему бы вам просто не использовать Wireshark или tcpdump, чтобы посмотреть, что происходит «через провод»? Тогда вам не нужно гадать, и вы можете изменить свой код соответственно – Robert

ответ

0

Если другой конец посылает ответ по одной линии за раз, возможно, что ответ проходит через несколько пакетов. Между каждым пакетом вы исчерпаете доступные данные для чтения в сокете, а bytesAvailable вернет 0. То, что вы действительно хотите, - это подождать, пока сокет не будет закрыт.

Я не слишком хорошо знакомы с Qt, но я думаю, что-то вроде этого является то, что вы хотите:

QByteArray MainWindow::ask(const QByteArray &cmd) 
{ 
    this->consoleWindow->put_data_in_console(cmd); 
    this->socket->write(cmd + "\r\n"); 

    QByteArray resBuffer; 
     socket->waitForReadyRead(); 

    while(socket->isOpen()) 
    { 
     socket->waitForReadyRead(-1); 
     resBuffer.append(socket->readAll()); 
    } 
    return resBuffer; 
} 

Если вы хотите иметь одно соединение для нескольких запросов/ответов, вам нужен какой-то волшебный разделитель, чтобы пометить конец ответов и отсканировать его буфер.

0

Предположим, что сервер отправляет свои ответы по строкам.

  1. Приходит первая строка (или, может быть, даже ее часть, скажем, один байт).
  2. waitForReadyRead() unblocks.
  3. Ваша программа входит в цикл, так bytesAvailable> 0. (Эта проверка не нужна: Без Avaiable байт, waitForReadyRead() будет по-прежнему блокировать.)
  4. readAll() читает первую строку.
  5. Условие петли проверяется во второй раз: bytesAvailable == 0
  6. Метод заканчивается, возвращая только первую строку.

Почему бы вам не использовать readLine?

Смежные вопросы