Wir haben zwei Qt-Anwendungen. App1 akzeptiert eine Verbindung von App2 über QTcpServer
und speichert sie in einer Instanz von QTcpSocket* tcpSocket
. App1 führt eine Simulation mit 30 Hz durch.Wie verwende ich QTcpSocket für den häufigen Versand kleiner Datenpakete?
QByteArray block;
/* lines omitted which write data into block */
tcpSocket->write(block, block.size());
tcpSocket->waitForBytesWritten(1);
Der Empfänger Buchse hört die QTcpSocket :: readDataBlock Signal (in main/GUI: mit dem folgenden Code (von dem Haupt/GUI Gewinde) für jeden Simulationslauf wird ein QByteArray
bestehend aus ein paar Kilobyte geschickt thread) und gibt den entsprechenden Zeitstempel an die GUI aus.
Wenn App1 und App2 auf demselben System ausgeführt werden, sind die Pakete perfekt synchronisiert. Wenn App1 und App2 jedoch auf verschiedenen Systemen ausgeführt werden, die über ein Netzwerk verbunden sind, ist App2 nicht mehr synchron mit der Simulation in App2. Die Pakete kommen viel langsamer. Noch überraschender (und anzeigend, dass unsere Implementierung falsch ist) ist die Tatsache, dass, wenn wir die Simulationsschleife stoppen, keine Pakete mehr empfangen werden. Das überrascht uns, weil wir vom TCP-Protokoll erwarten, dass alle Pakete irgendwann ankommen.
Wir haben die TCP-Logik basierend auf Qt fortune example gebaut. Der Vermögenserver ist jedoch anders, weil er nur ein Paket pro ankommendem Client sendet. Könnte jemand herausfinden, was wir falsch gemacht haben?
Hinweis: Wir verwenden MSVC2012 (App1), MSVC2010 (App2) und Qt 5.2.
Edit: Mit einem Paket, das ich das Ergebnis eines einzigen Simulationsexperiment bedeuten, die eine Reihe von Zahlen ist, in QByteArray block
geschrieben. Die ersten Bits enthalten jedoch die Länge von QByteArray, so dass der Client prüfen kann, ob alle Daten empfangen wurden. Dies ist der Code, der aufgerufen wird, wenn das Signal QTcpSocket :: readDataBlock emittiert wird:
QDataStream in(tcpSocket);
in.setVersion(QDataStream::Qt_5_2);
if (blockSize == 0) {
if (tcpSocket->bytesAvailable() < (int)sizeof(quint16))
return; // cannot yet read size from data block
in >> blockSize; // read data size for data block
}
// if the whole data block is not yet received, ignore it
if (tcpSocket->bytesAvailable() < blockSize)
return;
// if we get here, the whole object is available to parse
QByteArray object;
in >> object;
blockSize = 0; // reset blockSize for handling the next package
return;
TCP keine Pakete/Pakete hat - es ist nur ein Byte-Stream. Wie haben Sie die Daten aufgeschnitten? Wie weiß Ihre empfangende Anwendung, wenn 1 Ihrer eigenen Datenpakete beginnt und ein anderes Ende?Außerdem hat TCP eine Flusskontrolle. Wenn Sie also aufhören, Daten zu lesen, füllen sich die Puffer im TCP-Stack und es werden keine Daten mehr gesendet (und der Sender blockiert, wenn Sie versuchen, zu senden, solange Ihre Sockets nicht blockiert sind). Es ist jedoch sehr schwer zu erraten, was Sie falsch machen, wenn wir nicht wissen, was Sie tun oder wie Ihre Simulation funktioniert oder wie sie irgendwie "nicht synchron" wird. – nos
Ich habe versucht, Ihre Frage zu beantworten, indem ich meine ursprüngliche Frage bearbeitete. Bitte sehen Sie es sich an. –
Es scheint, dass Sie riskieren, mehr Daten zu lesen, als Sie möchten, wenn z. Deine Blockgröße ist 1024, aber 'tcpSocket-> bytesAvailable()' hat 1222 Bytes zur Verfügung, du liest auch den Anfang des nächsten Blocks, so wie es aussieht - also musst du 'in.readBytes() benutzen 'stattdessen, wo Sie angeben können, wie viel gelesen werden soll. (Und überprüfen Sie danach, dass es tatsächlich so viele Daten liest). Das hängt aber auch davon ab, wie Ihr Protokoll ist. Wenn z.B. Es ist eine einfache Anfrage/Antwort, bei der Ihr Sender * niemals * Daten sendet, bis er eine Antwort für das vorherige Paket erhalten hat. Der aktuelle Code scheint in Ordnung – nos