I'm writing a program to send files between a client and a server through local network in C++ with Qt_5.9 and the transfer stops randomly (sometimes at ~400MB, but sometimes at way less).
Here is the method writing the file content on the socket (in servertcp.cpp) :
void ServerTcp::write_file(QString fileName){
QFile file(fileName);
if(file.open(QIODevice::ReadOnly)){
qint64 nb = 0;
while(nb < file.size()){
QByteArray partial = file.read(65536);
clientConnection->write(partial, partial.count());
// I think I have to write something here
qint64 nbb = partial.count();
nb += nbb;
qDebug() << nbb << " (" << nb << ")";
}
file.close();
clientConnection->write("[[[END]]]");
}
}
And here is the method reading (called when readyRead
is emitted) the socket (in clienttcp.cpp) :
void ClientTcp::read()
{
qDebug() << "To read : " << soc.size();
emit to_IHM_text(soc.readAll());
}
The problem I face is that at some point, the client stops reading the socket (meaning we don't enter in the read
method anymore, so I guess readyRead
isn't emitted), but the server still writes in it (and in the task manager I can see the memory use increasing).
Can anyone tell me what I'm doing wrong ? (apart from using TCP for file transfer when FTP exists)
I tried inserting clientConnection->waitForReadyRead(X)
in the write_file
method, but it always waits X ms regardless the socket state.
Edit:
So I updated my write_file
method to check the connection state :
void ServerTcp::write_file(QString fileName){
QFile file(fileName);
if(file.open(QIODevice::ReadOnly)){
qint64 nb = 0;
while(nb < file.size()){
QByteArray partial = file.read(65536);
if(clientConnection->bytesToWrite()>0){
problem = true;
qDebug() << clientConnection->bytesToWrite();
clientConnection->waitForBytesWritten();
}
qDebug() << clientConnection->state();
qint64 nbb = clientConnection->write(partial, partial.count());
nb += nbb;
qDebug() << nbb << " (" << nb << ")";
}
file.close();
clientConnection->write("[[[END]]]");
}
}
And it always prompts QAbstractSocket::ConnectedState
during all the file transfer, meaning the problem is elsewhere.
Apparently, even if clientConnection->write(...)
always returns 65536 (except for last chunk of the file), the socket randomly refuses to effectively write the bytes (as clientConnection->bytesToWrite()
returns multiples of 65536 after a while).
Concerning the way the client knows it received the whole file, I use a homemade handshake with a header sent apart (file name + size) and a response (ok to receive or not ok).
Edit 2 :
I tried another way (connecting the socket bytesWritten
signal to a method which only sends a small part of the file), and same applies : at some point, it seems that congestion occurs...