I just try copy image with QDataStream. But failed :(
Code:
wds << ods; ftulis.close(); file.close();
Have any suggestion ?
Sorry, my english is bad :)
Printable View
I just try copy image with QDataStream. But failed :(
Code:
wds << ods; ftulis.close(); file.close();
Have any suggestion ?
Sorry, my english is bad :)
datastream wont work because it puts some header information in the file.. which will corrupt the png file.
just use simple fopen, fread, and fwrite or C library or use fstream of c++. If you just want to copy a file.. take a look at QFile::copy()
I want learn how to send file with socket. So before that, i must learn how to copy file with use QDataStream. Or, you can give me simple code about send file with socket ? I have read some sample code how to send file via socket, but complex and so hard for me :(
<i>Sorry, my english is bad :)</i>
why data stream is needed for socket?
just read the file
I just try. But failed. This in my code. Can you help me for fix it ?
Thank's before
Btw, I created project with Qt-creator
Server Code
main.cpp
Code:
#include <QtCore/QCoreApplication> #include "server.h" int main(int argc, char *argv[]) { Server server; { qCritical( "Cannot listen to port 9876." ); return 1; } return a.exec(); }
server.h
Code:
#ifndef SERVER_H #define SERVER_H #include <QtNetwork> { public: Server(); protected: void incomingConnection( int descriptor ); }; #endif
server.cpp
Code:
#include "server.h" #include "thread.h" { } void Server::incomingConnection( int descriptor ) { ServerThread *thread = new ServerThread( descriptor, this ); connect( thread, SIGNAL(finished()), thread, SLOT(deleteLater()) ); thread->start(); }
thread.h
Code:
#ifndef THREAD_H #define THREAD_H #include <QtNetwork> #include <QtGui> { public: void run(); private: int m_descriptor; }; #endif
thread.cpp
Code:
#include "thread.h" { m_descriptor = descriptor; } void ServerThread::run() { QTcpSocket socket; if( !socket.setSocketDescriptor( m_descriptor ) ) { qDebug( "Socket error!" ); return; } socket.write( data ); socket.disconnectFromHost(); //socket.waitForDisconnected(); }
Client Code
main.cpp
Code:
#include <QtGui/QApplication> #include "dialog.h" int main(int argc, char *argv[]) { Dialog w; w.show(); return a.exec(); }
dialog.h
Code:
#ifndef DIALOG_H #define DIALOG_H #include <QtGui> #include <QtNetwork> namespace Ui { class Dialog; } { Q_OBJECT public: ~Dialog(); private: Ui::Dialog *ui; QTcpSocket socket; private slots: void on_pushButton_clicked(); void tcpReady(); }; #endif // DIALOG_H
dialog.cpp
Code:
#include "dialog.h" #include "ui_dialog.h" { ui->setupUi(this); connect( &socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(tcpError(QAbstractSocket::SocketError)) ); connect( &socket, SIGNAL(readyRead()), this, SLOT(tcpReady()) ); } Dialog::~Dialog() { delete ui; } void Dialog::on_pushButton_clicked() { socket.abort(); socket.connectToHost( ui->lineEdit->text(), 9876 ); } void Dialog::tcpReady() { ds << ar; file.close(); } { return; tr("TCP error: %1").arg( socket.errorString() ) ); ui->label->setText( tr("<i>No Image</i>") ); ui->pushButton->setEnabled( true ); }
what is the error?
a quick look shows that at the server side you did not open the file before readAll().
1. open the file before reading it on server side
2. dont use QDataStream on client side - use just file.write(data);
3. When you send data through the network there is possibility that not all your data would be send in one network packet so the clients readAll() can give you less data than you sent from server! in your case it can result in corrupted image file. The best way is to make some header to your sent data like this:
client:
if your image is quite small then there is high possibility that it would be sent in one part,Code:
int size = readSize(socket.read(sizeof(int)); // now check withc bytesAvailable()if you got all data // and read them, if not all you have to wait for next part and append // it to the already downloaded part data = socket.readAll(); // or data.append(socket.readAll());
so the method I described would be necessary, but who knows :]
Server
How send size and data ?Code:
int size=data.size(); socket.write( data ); socket.disconnectFromHost();
Client
Code:
int size=readSize(socket.read(sizeof(int))); file.write(ar) file.close();
How declared readSize ?
you can assume that you size can be stored in 32-bit (4 byte) long int - you can use qint32 (or even quint32 - size can't be less then 0).
so you have to convert quint32 into QByteArray, writing there byte by byte of your quint32, something like this:
on the client side you have to create a valid quint32 from a byte array:Code:
quint32 size = ...; // your size QByteArray intBytes; for (int i = 0; i < 4; ++i) { quint8 b = (size >> (i*8)) & 0x000000ff; intBytes.append(b); }
(should work but i did not check so try to print the int first to see if it is what you have sent :])Code:
quint32 size = 0; // init with 0 to be sure there is really 0 for (int i = 0; i < 4; ++i) { quint8 b = intBytes.at(i); size |= (((quint32)b) & 0x000000ff) << i*8; }
now you have the size, so whenever readyRead() comes from socket you have to check int the slot if you have to start reading new image (read size and some of data) or you are in the middle of image data. Whenever you read image data just check if bytesAvailable() are equal to the needed size, if less than readAll() and decrease size by a number of bytes you already read. and so on... In other words reading data becomes a little state machine :] so you have to react adequately to the state you are in.
P.S. And it is nice to check if file was opened succesfully, so instead of this:
better do it like this:
Code:
// do something proper if cannot open file, e.g.: qDebug("Cannot open file!"); return; }
Not work. But thank's
I think not right to me for learn about QtNetwork now. Maybe next time
Code:
QTcpSocket socket; if( !socket.setSocketDescriptor( m_descriptor ) ) { qDebug( "Socket error!" ); return; } { qDebug("Cannot open file!"); return; } int size=data.size(); for(int i=0; i< 4; ++i) { quint8 b=(size >> (i*8)) & 0x000000ff; data.append(b); } socket.write(data); socket.disconnectFromHost();
Client
Code:
void Dialog::tcpReady() { quint32 size=0; for(int i=0; i < 4; ++i) { quint8 b=ar.at(i); size |= (((quint32)b) & 0x000000ff) << i*8; } file.write(ar); file.close(); }
Once more, thank's for your help
Men you have appended your size to the end of the data! What is the sense of doing that if you have to know the size at the very beginning of receiving data??? You have to send the size, and then the data:
it is not that hard to invent that idea.Code:
QTcpSocket socket; if( !socket.setSocketDescriptor( m_descriptor ) ) { qDebug( "Socket error!" ); return; } { qDebug("Cannot open file!"); return; } int size=data.size(); QByteArray sizeBytes; for(int i=0; i< 4; ++i) { quint8 b=(size >> (i*8)) & 0x000000ff; sizeBytes.append(b); } sizeBytes.append(data); socket.write(sizeBytes); socket.disconnectFromHost();
And you dont even use that information about size on the client side.
Tell me what happend if you do it like this:
Code:
void Dialog::tcpReady() { int bytesAvail = socket.bytesAvailable() - 4; quint32 size=0; for(int i=0; i < 4; ++i) { quint8 b=ar.at(i); size |= (((quint32)b) & 0x000000ff) << i*8; } if (size > bytesAvail) qDebug("Different sizes!!!"); else qDebug("All data have been delivered!"); ar = socket.readAll(); file.write(ar); file.close(); }
As I see you have to read about network at all...Quote:
I think not right to me for learn about QtNetwork now.
Thank's because you keep teach me....
And... your sample code work now :)
Btw, I must put this line in server side
Code:
socket.waitForDisconnected();
Sorry, my english is so bad :(