Использование QTcpSocket для непрерывного быстрого использования

Мне нужно реализовать клиент, который читает данные с частотой 300 Гц (300 выборок в секунду). При работе с сокетами C все было в порядке, с тем, что мне нужно запустить непрерывный цикл while для получения данных с сервера (который блокирует работу клиента от чего-либо еще). Итак, я решил попытаться перейти на QTcpsocket, чтобы обрабатывать сигналы, поступающие от другого объекта к клиентскому объекту. Но когда я подключаю Qtcpsocket, и подключаю сигнал для чтения

connect(socket,&QTcpSocket::readyRead, this, &client::handleReadyRead, Qt::ConnectionType::QueuedConnection);

это мой обработчик -

QByteArray b = socket->read(12);
int packetLength = (unsigned char)b[6] << CHAR_BIT;
packetLength |=  (unsigned char)b[7];
b = socket->read(packetLength);

(Я получаю 12-байтовый заголовок для каждого пакета) Теперь я получаю очень медленный клиент - он обрабатывает примерно 3 выборки в секунду... Я проверил, сколько bytesavailable() возвращается, и похоже, что данные накапливаются в буфере сокетов. Что я делаю неправильно? Я должен получить очень быстрый клиент, но я не уверен, что способ, которым я читаю, является оптимальным. Есть ли более эффективный способ сделать это?

Спасибо

1 ответ

Решение

Ваш текущий handleReadyRead предполагает, что полный пакет доступен для чтения и границы пакета сохранены. TCP не работает таким образом - это просто поток байтов.

Лучшим подходом может быть накопление данных в QByteArray и читать пакеты из этого QByteArray как и когда они станут доступны.

Итак, при условии вашего client класс имеет член данных...

QByteArray m_data;

Я ожидаю, что логика будет что-то вроде...

void handleReadyRead ()
{

  /*
   * Append all available data to m_data.
   */
  m_data.append(socket->readAll());

  /*
   * Now work our way through m_data processing complete
   * packets as we find them.  At any given point offset
   * is the total size of all complete packets (including
   * headers) processed thus far.
   */
  int offset = 0;
  while (m_data.length() >= offset + 12) {

    /*
     * We have enough data for a header so read the packet length.
     */
    int packetLength  = (unsigned char)m_data[offset + 6] << CHAR_BIT;
    packetLength     |= (unsigned char)m_data[offset + 7];

    /*
     * Check to see if we have sufficient data for the packet
     * body.  If not then we're done for the time being.
     */
    if (m_data.length() < offset + 12 + packetLength)
      break;

    /*
     * There is enough data for the complete packet so read it.
     * Note that the following will include the header data in the
     * packet variable.  If that's not desired then change it to...
     *
     *   auto packet = m_data.mid(offset + 12, packetLength);
     */
    auto packet = m_data.mid(offset, 12 + packetLength);

    /*
     * Do whatever you want with the packet.
     */
    do_something_with_the_packet(packet);

    /*
     * Update the offset according to the amount of data read.
     */
    offset += 12 + packetLength;
  }

  /*
   * Finally, remove the data processed from the beginning of
   * the QByteArray.
   */
  if (offset)
    m_data = m_data.right(data.size() - offset);
}

Вышеприведенное не проверено, но, безусловно, соответствует тому коду, который я использовал в прошлом.

Другие вопросы по тегам