2017-06-21 5 views
0

Je dois implémenter un client qui lit les données à 300 Hz (300 échantillons par seconde). Lorsque je travaillais avec des sockets C, tout allait bien accepter le fait que j'ai besoin d'exécuter une boucle while continue pour obtenir les données du serveur (ce qui empêche le client de gérer quoi que ce soit d'autre). J'ai donc décidé d'essayer de passer à QTcpsocket, afin de gérer les signaux provenant d'autres objets vers l'objet client. Mais quand je connecte le QTcpSocket et connecter le signal pour la lectureUtilisation de QTcpSocket pour une utilisation rapide continue

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

c'est mon gestionnaire -

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

(je reçois un pour chaque paquet tête longue de 12 octets) Maintenant, je reçois très client lent - Il gère environ peut-être 3 échantillons par seconde ... J'ai vérifié pour voir combien retourne bytesavailable(), et il semble que les données s'accumulent dans le tampon de sockets. Qu'est-ce que je fais de mal? Je dois obtenir un client très rapide, mais je ne suis pas sûr que la façon dont je lis est optimale. Existe-t-il un moyen plus efficace de le faire?

Merci

+2

Profil de votre application et voir où se trouve le goulot d'étranglement. –

+0

Je suis en train d'utiliser un mini-projet pour le tester, donc c'est à peu près le fonctionnement du client. Le profilage montre que la boucle d'événements prend beaucoup de temps, mais peut-elle être évitée? – JLev

+0

Vous appelez 'socket-> read (packetLength)' sans savoir si les octets 'packetLength' sont disponibles ou non. Si ce n'est pas le cas, la lecture suivante ne sera plus synchronisée avec le flux de données. –

Répondre

1

Votre courant handleReadyRead suppose qu'un paquet complet est disponible à lire et que les limites de paquets sont conservés. TCP ne fonctionne pas de cette façon - c'est juste un flux d'octets.

Une meilleure approche pourrait consister à accumuler des données dans un QByteArray et à lire des paquets à partir de ce QByteArray dès qu'ils seront disponibles.

Donc, en supposant que votre client classe a un membre de données ...

QByteArray m_data; 

Je pense la logique à quelque chose comme ...

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); 
} 

Ce qui précède est non testé, mais est certainement le long des lignes de code que j'ai utilisé dans le passé.

+0

Cela fonctionne vraiment, merci. Maintenant, je viens de découvrir pourquoi je reçois les paquets dans un mauvais ordre .... – JLev