Seite 1 von 1
[gelöst] QSocket- QDataStream
Verfasst: 4. Dezember 2007 09:38
von stonecold
Hallo,
ich verschicke eine Struktur übers Netzwerk (Localhost). Dazu nutze ich die Klasse QDataStream. Es scheint eigentlich auch gut zu funktionieren.
Hier mal die wichtigsten Codeteile.
Client:
Code: Alles auswählen
void client::sendToServer()
{
myStruct ms;
ms.lat = 88.89;
char data[sizeof(myStruct )];
memcpy(data, &ms, sizeof(myStruct ));
QDataStream dataStream(socket);
dataStream.setVersion(6);
dataStream.writeRawBytes( data, sizeof(myStruct ) );
std::cout << "client::sendToServer(): " << std:: endl;
}
Server:
Code: Alles auswählen
void server::incomingDataSlot()
{
QSocket* nsocket =(QSocket*)sender();
QDataStream dataStream( nsocket );
dataStream.setVersion(6);
myStruct ms;
char data[sizeof(myStruct)];
dataStream.readRawBytes( data, sizeof(myStruct) );
memcpy(&ms, data, sizeof(myStruct));
std::cout << "ms.lat = " << ms.lat << std::endl;
}
Nun die Frage. Ist mit der derzeitigen Umsetzung garantiert, dass die Daten immer vollständig beim Server ankommen auch wenn mehrere Pakete verschickt werden?
Wenn nicht, wie kann ich das am besten umsetzen?
Mal zum Verständnis, wo genau werden die Daten in Pakete geteilt, verschickt und wieder zusammengebaut? Muss ich mich da überhaupt drum kümmern?
Verfasst: 4. Dezember 2007 10:59
von stonecold
Clientseitig scheinen die zu übertragenden Daten in mehrere Pakete aufgeteilt zu werden. Kann ich das verhindern? Wenn nicht woher weiß ich dann welche Pakete wie zusammen gehören?
Verfasst: 4. Dezember 2007 12:44
von stonecold
Okay, habe jetzt selbst ne Lösung gefunden.
Code: Alles auswählen
while(socket->bytesAvailable() != sizeof(data))
{
socket->waitForMore(10);
}
socket->readBlock( data, sizeof(data) );
Muss natürlich noch in Richtung Timeout verbessert werden.....
Verfasst: 4. Dezember 2007 14:00
von Christian81
Daten erst in ein QByteArray speichern und wenn genug Daten da -> konvertieren.
Verfasst: 6. Dezember 2007 16:08
von stonecold
Hallo Christian,
ich habe gerade ein Problem und dein Hinweis
>>> Daten erst in ein QByteArray speichern und wenn genug Daten da -> konvertieren.
könnte die Lösung sein. Verstehe ich das richtig?
Die eingehenden Daten werden im Array gespeichert anschl. frage ich die Größe ab. Ist die Arraygröße dann >= der Erwartenden Nachricht kopiere ich die Daten aus den Array raus und lösche sie dann in dem Array (FIFO)?
Warum kommen die Pakete nicht komplett an, also warum wird der incomming-Slot nicht erst dann aufgerufen wenn die Daten komplette da sind? Der Server weiß doch wie groß sie sein müssen? Kann ich mich darauf verlassen, dass die Pakete in der richtigen Reihenfolge kommen?
Leider werde ich aus der Doku nicht richtig schlau. Weißt du wo ich ggf. ein Beispiel finde?
Danke und Gruß
Verfasst: 6. Dezember 2007 16:14
von Christian81
Sie kommen immer in der richtigen Reihenfolge an - sonst würde TCP irgendwie nicht korrekt funktionieren. Die Daten werden aber in Stücke zu xx byte zerteilt (netzwerk-Grundwissen) - deshalb kommt ein 'bytesReceived()' immer an wenn Daten vorhanden sind. Deine Netzwerkkarte weiss ja nichts von deiner Datenstruktur.
Verfasst: 6. Dezember 2007 17:56
von stonecold
Okay danke. Soweit war es mir eigentlich klar. Ich gehe mal davon aus, dass wenn Daten kommen, die noch nicht die richtige Reihenfolge weil beispielsweise noch ein Paket fehlt der Aufruf auch nicht erfolgt?!
Bleibt noch mein QByteArray-Problem.
Verfasst: 7. Dezember 2007 09:41
von stonecold
Hallo Christian,
ich versuche gerade die empfangenen Daten in ein QByteArray zu schreiben und erst wenn genug Daten diese dann weiter zu leiten.
Es geht auch anders deshalb mal meine erste Frage:
Warum die Daten im Array zwischenspeichern? Ich will das nicht einfach machen ohne genau zu wissen warum.
Möglich wäre doch auch:
Code: Alles auswählen
//...
char data[messageSize]
//...
//... incommingDataSlot
if(socket->bytesAvailable() >= messageSize)
{
socket->readBlock( data, messageSize );
emit incommingDataSignal( data, messageSize );
}
So dann versuche ich jetzt die Daten zu speichern, Mein Ansatz:
Code: Alles auswählen
//... incommingDataSlot
QSocket* socket =(QSocket*)sender();
QDataStream dataStream( socket );
dataStream >> *dataMemory; // dataMemory -> QByteArray*
if( dataMemory->size() >= messageSize )
{
}
Aber wie geht's in der Schleife nun weiter?
Muss ich die Daten jetzt mittels memcpy in das char-Array speichern und die Daten aus den ByteArray löschen??? Habe irgendwie keine interessante Funktion gefunden
und finde das Vorgehen deshalb und nicht zuletzt Aufgrund meiner Unwissenheit über die Sachen mit dem ByteArray ziehmlich umständlich.
Danke und Gruß,
Mario
Verfasst: 7. Dezember 2007 11:18
von Christian81
Du kannst natürlich auch abfragen ob genug Daten vorhanden sind und ansonsten das event einfach ignorieren. Würde das umkopieren in das QByteArray sparen.
Verfasst: 7. Dezember 2007 11:26
von stonecold
Okay, THX!