2017-10-12 5 views
2

J'ai QTcpServer. Je veux envoyer de grandes données du côté du client et comment attraper le signal, quand toutes les données sont reçues sur le serveur? "while (socket-> octetsavailable)" ne fonctionne pas.QTcpSocket readyRead() Signal émis deux fois

Par exemple:

quand QByteArray taille est 9000, qui est envoyé du client, sur le serveur, il est 4000 ou 5000 ...

Exemple Deux:

Dans ce Case readyRead() SIGNAL Est émis 8 fois.

void Client::SendMessage(std::vector<QString>) 
{ 
    MyClass _Send; 
      _Send.Age = 22; 
      _Send.School = 14; 
      _Send.Name = "Taz"; 

    QVector<MyClass2> vv; 

    for (int i = 0; i < 15000; i++) { 
     vv.push_back(MyClass2(24, "leri")); 
     vv.push_back(MyClass2(22, "tazo")); 
    } 

    _Send.vctr = vv; 

    QByteArray bytes; 
    QDataStream stream(&bytes, QIODevice::WriteOnly); 

    int FunctionUID = 331; 
    int ij, ik = ij = 169; 
    MyClass2 faf(-31, "15"); 

    stream << FunctionUID << _Send << faf << ij << ik; 

    socket->write(bytes); 
} 



void Server::ImReady() 
{ 
    QByteArray buf; 

    buf = socket->readAll(); 

    QDataStream stream(&buf, QIODevice::ReadOnly); 

    int FunctionUID, ij, ik; 
    MyClass vv; 
    MyClass2 vv1; 

    stream >> FunctionUID >> vv >> vv1 >> ij >> ik; 

    qDebug() << vv.vctr.size() << "faf"; 
} 

void Server::incomingConnection(qintptr val) 
{ 
    qDebug() << "Client Connected" << val; 

    socket = new QTcpSocket; 
    socket->setSocketDescriptor(val); 

    if (!socket) { 
     return; 
    } 

    connect(socket, SIGNAL(disconnected()), socket, SLOT(deleteLater())); 
    connect(socket, SIGNAL(readyRead()), this, SLOT(ImReady())); 
} 
+0

Les données ne sont pas toujours envoyées sous la forme d'un seul paquet. Si elle est assez grande, elle peut être envoyée sous forme de blocs de données. C'est probablement pourquoi vous obtenez plusieurs signaux 'readyRead'. – vahancho

+0

Si vous utilisez Qt 5.7 ou plus récent, vous pouvez tirer parti de [lire les transactions] (http://doc.qt.io/qt-5/qdatastream.html#using-read-transactions) dans 'QDataStream'. Jetez un coup d'œil à l'exemple [client de fortune] (http://doc.qt.io/qt-5/qtnetwork-fortuneclient-example.html) pour voir comment il peut être implémenté. – thuga

Répondre

3

TCP n'envoie pas de messages, c'est un flux de données. Cela signifie que vous ne pouvez pas lire toutes les données présentes et considérer ce message. Au lieu de cela, on envoie généralement un en-tête, contenant la taille du message, puis le destinataire sait combien de lire pour obtenir le message entier (et juste celui-ci, pas lu dans le suivant).

Cela signifie que votre emplacement ferait quelque chose comme ça

void Server::ImReady() 
{ 
    uint32 size; 
    socket->read(&size, 4); 
    uint32 readTotal = 0; 
    do { 
    readTotal += socket->read(buffer, size-readTotal); 
    } while (readTotal < size); 
} 

Vous pouvez mettre une ligne comme

if (socket->bytesAvailable() == 0) 
    return; 

au début de la fente, et vous ne se souciera pas du tout si le le signal est émis plus d'une fois par message. Notez que le code ci-dessus nécessite une gestion d'erreur supplémentaire, par ex. vous devez vous assurer que le premier read lit tous les 4 octets, et gère toujours une valeur de retour de -1.

+0

je pense, ceci est très helpfull.but j'ai le problème de somme, il est maintenant avec moi 'uint32' et aucun appel correspondant socket-> read (QByteArray) – Taz742

+0

Il y a des surcharges pour 'QTcpSocket :: read', on utilisant un octet array et renvoyant le nombre d'octets lus, et l'autre retournant un 'QByteArray'. Vous devez adapter le code en fonction de celui que vous utilisez. Le code dans la réponse utiliserait le tableau d'octets, 'buffer' serait un simple' char [] ' –

+0

Merci ce problème est résolu) – Taz742