[solved] QT4: Datei übers Netzwerk versenden mit Q3Socket
-
-=Freaky=-
- Beiträge: 503
- Registriert: 29. Dezember 2006 22:54
- Wohnort: HL
ok, ich habe mir jetzt Qt4 open-source installiert und das programm so umgebaut, dass die daten im QByteArray erst mit ba.toBas64() kodiert und auf der server seite mit ba2 = QByteArray::fromBase64( ba1 ) dekodiert werden. jetzt liegt mein problem noch in dem prüfzeichen am ende. wie kann ich das noch mit reinbringen, dass es mitgesendet und im server danach geprüft wird?
ich habe versucht einfach per QDataStream nach dem toBase64() in das QByteArray noch ein 'µ' zu schreiben ( out << 'µ'; ), weiss aber nicht wie ich die prüfung im server jetzt implementieren soll. immer erst in ein QByteArray und dann in einen character einlesen geht ja nicht, da nur im letzten paket noch ein character dabei ist.
bitte helft mir noch einmal!
mfg,
julian
ich habe versucht einfach per QDataStream nach dem toBase64() in das QByteArray noch ein 'µ' zu schreiben ( out << 'µ'; ), weiss aber nicht wie ich die prüfung im server jetzt implementieren soll. immer erst in ein QByteArray und dann in einen character einlesen geht ja nicht, da nur im letzten paket noch ein character dabei ist.
bitte helft mir noch einmal!
mfg,
julian
-
-=Freaky=-
- Beiträge: 503
- Registriert: 29. Dezember 2006 22:54
- Wohnort: HL
genau da war mein problem. in welcher form soll ich denn die daten verschicken? ich denke QByteArray. aber die steuerzeichen müssten dazugeschrieben werden. also so habe ich es jetzt gemacht (client.cpp):Du könntest z.B. so lange einlesen, solange neue Daten vorhanden sind
Code: Alles auswählen
QByteArray block;
QDataStream out( &block, QIODevice::WriteOnly );
out.setVersion( 5 );
out << file.readAll();
block.toBase64();
out << 'µ';
socket.writeBlock( block.data(), block.size() );Code: Alles auswählen
QByteArray temp;
in >> temp;verstehst du wo mein problem liegt?
und noch eine frage:
im server, wie soll ich die einzelnen blocks speichern? eine QByteArray-element in der server-klasse und bei signal readyRead() in readClient() immer den gelesenen block dranhängen (wenn kein steuerzeichen dabei ist) ?
mfg,
julian
Code: Alles auswählen
void readData() {
readBlock<<readAll();
do {
int stop=readBlock.indexOf('µ');
if (stop!=-1) {
QByteArray myData=readBlock.left(stop-1);
yourParseFkt(myData);
readBlock.remove(0, stop+1);
}
while (stop!=-1);
}
-
-=Freaky=-
- Beiträge: 503
- Registriert: 29. Dezember 2006 22:54
- Wohnort: HL
ok, ein stückchen code sagt mehr als 1000 worte, aber ich brauche wohl 2000.
also hier ein paar fragen:
readData() ist verbunden mit dem readyRead()-signal ?
readBlock ist ein QByteArray, aber in der 1. zeile muss es ein QDataStream sein (der in das QByteArray schreibt) ?
diese do...while schleife verstehe ich nicht. ist das desselbe wie while(){...} ?
warum steht da ungleich( != ), müsste da nicht gleich ( == ) stehen? dasselbe in der if-schleife in der while-schleife ?
yourParseFkt(): die funktion, in der alle gelesenen QByteArray-pakete aneinandergehängt werden (bzw. jeweils das gerade gelesene wird dranhegängt) ?
danke für alle antworten!
mfg,
julian
also hier ein paar fragen:
readData() ist verbunden mit dem readyRead()-signal ?
readBlock ist ein QByteArray, aber in der 1. zeile muss es ein QDataStream sein (der in das QByteArray schreibt) ?
diese do...while schleife verstehe ich nicht. ist das desselbe wie while(){...} ?
warum steht da ungleich( != ), müsste da nicht gleich ( == ) stehen? dasselbe in der if-schleife in der while-schleife ?
yourParseFkt(): die funktion, in der alle gelesenen QByteArray-pakete aneinandergehängt werden (bzw. jeweils das gerade gelesene wird dranhegängt) ?
danke für alle antworten!
mfg,
julian
Hy!
Wenn ichs richtig verstanden hab dann wird der Code von upsala mehrere Blocke die hintereinander kommen zerteilen, und dann mit den jeweiligen Daten die Funktion yourParseFkt aufrufen.
Welchen Typ readBlock hat hab allerdings auch nicht mitbekommen, da QByteArray keinen operator<< hat und QDataStream kein indexOf().
readData muss dafür mit dem readyRead signal verbunden sein.
!= passt schon, du willst ja nur dann zerteilen und parsen wenn du eine gültige Datei empfangen hast.
Aneinandergehängt werden die Daten schon in dieser Funktion da, readBlock ein Member deiner Klasse sein muss, und myParseFkt erst aufgerufen wird wenn ein komplettes Files vorhanden ist.
Wenn ich richtig gedacht habe sollte das funktionieren wenn du einfach statt operator<< operator+= verwendest, allerdings nicht getestet. Dazu muss du readBlock noch zum Klassenmember, oder static machen
mfg
uhu01
Wenn ichs richtig verstanden hab dann wird der Code von upsala mehrere Blocke die hintereinander kommen zerteilen, und dann mit den jeweiligen Daten die Funktion yourParseFkt aufrufen.
Welchen Typ readBlock hat hab allerdings auch nicht mitbekommen, da QByteArray keinen operator<< hat und QDataStream kein indexOf().
readData muss dafür mit dem readyRead signal verbunden sein.
!= passt schon, du willst ja nur dann zerteilen und parsen wenn du eine gültige Datei empfangen hast.
Aneinandergehängt werden die Daten schon in dieser Funktion da, readBlock ein Member deiner Klasse sein muss, und myParseFkt erst aufgerufen wird wenn ein komplettes Files vorhanden ist.
Wenn ich richtig gedacht habe sollte das funktionieren wenn du einfach statt operator<< operator+= verwendest, allerdings nicht getestet. Dazu muss du readBlock noch zum Klassenmember, oder static machen
mfg
uhu01
Stimmt, wenn man nicht alles testet bevor man es hierhin schreibt 
Es muß readBlock+=readAll() heißen. Da wir hier unsere Daten von einem Netzwerk-Socket bekommen, sollten wir alle empfangenen Daten über QIODevice::readAll() einlesen können. readAll muß natürlich eine Klassenveriable vom Typ QByteArray sein (static würde ich nicht machen, könnte nach hinten losgehen...)
do...while sind C++-Grundlagen...
yourParseFkt(QByteArray) ist deine Funktion, die einen vollständigen Datenblock auswertet (Bilder, Texte...)
Es muß readBlock+=readAll() heißen. Da wir hier unsere Daten von einem Netzwerk-Socket bekommen, sollten wir alle empfangenen Daten über QIODevice::readAll() einlesen können. readAll muß natürlich eine Klassenveriable vom Typ QByteArray sein (static würde ich nicht machen, könnte nach hinten losgehen...)
do...while sind C++-Grundlagen...
yourParseFkt(QByteArray) ist deine Funktion, die einen vollständigen Datenblock auswertet (Bilder, Texte...)
-
-=Freaky=-
- Beiträge: 503
- Registriert: 29. Dezember 2006 22:54
- Wohnort: HL
ok, ich habe das jetzt entsprechend geändert, aber wenn ich jetzt eine datei sende, wird yourParseFkt() 3 mal (4kb datei) bzw. ca. 180-200 mal (168kb datei) hintereinander aufgerufen, jedesmal kommt keine vollständige, heile datei datei da an, ich denke also dass für jeden einzelnen teil der datei, der ankommt, diese funktion aufgerufen wird.
die funktion sieht so aus:
entweder ich habe eure erklärungen nicht verstanden, oder es müsste eigentlich so funktionieren..tut es aber nicht.
achso ich habe das hier
war das vielleicht schon falsch?
mfg,
julian
die funktion sieht so aus:
Code: Alles auswählen
void ClientSocket::writeFile( QByteArray &block )
{
QString fileName = Q3FileDialog::getSaveFileName();
QFile file( fileName );
if( !file.open( QIODevice::WriteOnly ) )
{
QMessageBox::warning( 0, tr( "Server -Error" ), tr( "Datei konnte nicht zum Schreiben geöffnet werden!" ) );
return;
}
file.writeBlock( QByteArray::fromBase64( block ) );
QMessageBox::information( 0, tr( "Server - Information" ), tr( "Datei wurde geschrieben!" ) );
}achso ich habe das hier
jetzt so interpretiert, dass readBlock eine Klassenvariable vom typ QByteArray sein muss, so habe ich es dann auch gemacht.readAll muß natürlich eine Klassenveriable vom Typ QByteArray
war das vielleicht schon falsch?
mfg,
julian
-
-=Freaky=-
- Beiträge: 503
- Registriert: 29. Dezember 2006 22:54
- Wohnort: HL
so das isse:
mfg,
julian
Code: Alles auswählen
void ClientSocket::readClient()
{
readBlock += readAll();
int stop = -1;
do
{
stop=readBlock.indexOf('µ');
if (stop != -1)
{
QByteArray myData;=readBlock.left(stop-1);
writeFile( myData );
readBlock.remove(0, stop+1);
}
}while( stop != -1 );
if( state() == Idle )
deleteLater();
}julian
Hy!
Das sollte eigentlich so passen, hast du schon mal geschaut ob du wirklich ein 'µ' am Ende der Datenübertragung mitschickst?
Wenn du über den Socket nur ein File übertragen willst, dann kannst du den Socket löschen, sobald du das Ende Zeichen erhalten hast, bzw. sollte eigentlich eh die Gegenseite den Socket schließen.
Dann kannst du den mit dem Signal clientDisconnected den Socket löschen.
mfg
uhu01
Das sollte eigentlich so passen, hast du schon mal geschaut ob du wirklich ein 'µ' am Ende der Datenübertragung mitschickst?
Wenn du über den Socket nur ein File übertragen willst, dann kannst du den Socket löschen, sobald du das Ende Zeichen erhalten hast, bzw. sollte eigentlich eh die Gegenseite den Socket schließen.
Dann kannst du den mit dem Signal clientDisconnected den Socket löschen.
mfg
uhu01
-
-=Freaky=-
- Beiträge: 503
- Registriert: 29. Dezember 2006 22:54
- Wohnort: HL
ja, daran habe ich auch gedacht und es wird das richtige zeichen geschickt und geprüft. ich weiss nicht woran es liegt und denke auch ihr könntet das schneller/überhaupt herausfinden, deshalb habe ich den code des clients und des servers inkl. pro-file angehängt. ich wäre sehr dankbar, wenn es sich einmal jemand angucken könnte, viel code ist es ja nicht.
und ja, in diesem test möchte ich nur ein file übertragen, jedoch wird das am ende in dem fertigen programm mit dieser funktion voraussichtlich nicht so sein, dass nur ein file übertragen wird.
vielen dank im voraus!
mfg,
julian
und ja, in diesem test möchte ich nur ein file übertragen, jedoch wird das am ende in dem fertigen programm mit dieser funktion voraussichtlich nicht so sein, dass nur ein file übertragen wird.
vielen dank im voraus!
mfg,
julian
- Dateianhänge
-
- test.zip
- testprogramm
- (3.46 KiB) 205-mal heruntergeladen
-
-=Freaky=-
- Beiträge: 503
- Registriert: 29. Dezember 2006 22:54
- Wohnort: HL