[QTcpServer] Envoi d'un fichier
Bonsoir,
j'ai envoyé un fichier à partir de mon application client à un serveur. Mais mon fichier n'est pas reçu en totalité par le serveur.il y'a une chose qui cloche .
Ceci est ma fenetreClient.cpp
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
| #include "FenClient.h"
#include <QMenuBar>
#include <QMessageBox>
#include "qfiledialog.h"
#include <QDir>
FenClient::FenClient()
{
setupUi(this);
socket = new QTcpSocket(this);
connect(socket, SIGNAL(readyRead()), this, SLOT(donneesRecues()));
connect(socket, SIGNAL(connected()), this, SLOT(connecte()));
connect(socket, SIGNAL(disconnected()), this, SLOT(deconnecte()));
connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(erreurSocket(QAbstractSocket::SocketError)));
tailleMessage = 0;
}
// Tentative de connexion au serveur
void FenClient::on_boutonConnexion_clicked()
{
// On annonce sur la fenêtre qu'on est en train de se connecter
listeMessages->append(tr("<em>Tentative de connexion en cours...</em>"));
boutonConnexion->setEnabled(false);
socket->abort(); // On désactive les connexions précédentes s'il y en a
socket->connectToHost(serveurIP->text(), serveurPort->value()); // On se connecte au serveur demandé
}
// Appuyer sur la touche Entrée a le même effet que cliquer sur le bouton "Envoyer"
void FenClient::on_message_returnPressed()
{
on_boutonEnvoyer_2_clicked();
}
// On a reçu un paquet (ou un sous-paquet)
void FenClient::donneesRecues()
{
QTcpSocket *socket = qobject_cast<QTcpSocket *>(sender()); //--> permet de connaitre le client qui envoi les données (son socket)
if(socket == 0)
{
qDebug() << "Pas de Socket!";
listeMessages->append("Pas de Socket!");
return;
}
forever
{
QDataStream in(socket);
if(blockSize == 0)
{
if(socket->bytesAvailable()< sizeof(quint32 ))
{
qDebug() << "Erreur < sizeof(quint32))";
listeMessages->append("Erreur < sizeof(quint32))");
return;
}
in >> blockSize;
}
if(socket->bytesAvailable() < blockSize)
{
qDebug() << "données pas arriver en entier";
listeMessages->append("données pas arriver en entier)");
return;
}
qDebug() << "!!!!!!";
QByteArray dataOut;
QString nameFile;
in >> nameFile >> dataOut;
QFile fileOut(nameFile);
fileOut.open(QIODevice::WriteOnly);
fileOut.write(dataOut);
fileOut.close();
listeMessages->append("fichier reçu");
blockSize = 0;
}
}
// Ce slot est appelé lorsque la connexion au serveur a réussi
void FenClient::connecte()
{
listeMessages->append(tr("<em>Connexion réussie !</em>"));
boutonConnexion->setEnabled(true);
}
// Ce slot est appelé lorsqu'on est déconnecté du serveur
void FenClient::deconnecte()
{
listeMessages->append(tr("<em>Déconnecté du serveur</em>"));
}
// Ce slot est appelé lorsqu'il y a une erreur
void FenClient::erreurSocket(QAbstractSocket::SocketError erreur)
{
switch(erreur) // On affiche un message différent selon l'erreur qu'on nous indique
{
case QAbstractSocket::HostNotFoundError:
listeMessages->append(tr("<em>ERREUR : le serveur n'a pas pu être trouvé. Vérifiez l'IP et le port.</em>"));
break;
case QAbstractSocket::ConnectionRefusedError:
listeMessages->append(tr("<em>ERREUR : le serveur a refusé la connexion. Vérifiez si le programme \"serveur\" a bien été lancé. Vérifiez aussi l'IP et le port.</em>"));
break;
case QAbstractSocket::RemoteHostClosedError:
listeMessages->append(tr("<em>ERREUR : le serveur a coupé la connexion.</em>"));
break;
default:
listeMessages->append(tr("<em>ERREUR : ") + socket->errorString() + tr("</em>"));
}
boutonConnexion->setEnabled(true);
}
void FenClient::on_ouvrir_clicked()
{
QString fichier = QFileDialog::getOpenFileName(this, "Ouvrir un fichier", QString(), "objet 3D (*.off *.obj *.ply *.smf *.wrl)");
// QObject* parent = new QObject();
if ( fichier!=""){
QFileInfo fi(fichier);
QString name=fi.fileName();
// QString Newname="G:/appmemdos/compression/Release/"+name;
// bool valid = QFile::copy (fichier,Newname );//copier un fichier
lineEdit->setText(fichier);
}
}
void FenClient::on_boutonEnvoyer_2_clicked()
{
QString nomFichier = lineEdit->text();
QFile file(lineEdit->text());
if(!file.open(QIODevice::ReadOnly))
{
qDebug() << "Erreur Le fichier n'a pas pu être ouvert !";
return;
listeMessages->append("Erreur Le fichier n'a pas pu être ouvert !");
}
QByteArray bytes = file.readAll();
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out << quint32(0);
out << nomFichier;
out << bytes;
out.device()->seek(0);
out << quint32((block.size() - sizeof(quint32)));
qDebug() << "Etat : envoi en cours...";
listeMessages->append("Etat : envoi en cours...");
socket->write(block);
} |
et le serveur:
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
| #include "FenServeur.h"
FenServeur::FenServeur()
{
// Création et disposition des widgets de la fenêtre
etatServeur = new QLabel;
boutonQuitter = new QPushButton(tr("Quitter"));
connect(boutonQuitter, SIGNAL(clicked()), qApp, SLOT(quit()));
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(etatServeur);
layout->addWidget(boutonQuitter);
setLayout(layout);
setWindowTitle(tr("ZeroChat - Serveur"));
// Gestion du serveur
serveur = new QTcpServer(this);
if (!serveur->listen(QHostAddress::Any, 50885)) // Démarrage du serveur sur toutes les IP disponibles et sur le port 50585
{
// Si le serveur n'a pas été démarré correctement
etatServeur->setText(tr("Le serveur n'a pas pu être démarré. Raison :<br />") + serveur->errorString());
}
else
{
// Si le serveur a été démarré correctement
etatServeur->setText(tr("Le serveur a été démarré sur le port <strong>") + QString::number(serveur->serverPort()) + tr("</strong>.<br />Des clients peuvent maintenant se connecter."));
connect(serveur, SIGNAL(newConnection()), this, SLOT(nouvelleConnexion()));
}
tailleMessage = 0;
}
void FenServeur::nouvelleConnexion()
{
envoyerATous(tr("<em>Un nouveau client vient de se connecter</em>"));
QTcpSocket *nouveauClient = serveur->nextPendingConnection();
clients << nouveauClient;
connect(nouveauClient, SIGNAL(readyRead()), this, SLOT(donneesRecues()));
connect(nouveauClient, SIGNAL(disconnected()), this, SLOT(deconnexionClient()));
}
void FenServeur::donneesRecues()
{
QTcpSocket *socket = qobject_cast<QTcpSocket *>(sender()); //--> permet de connaitre le client qui envoi les données (son socket)
if(socket == 0)
{
qDebug() << "Pas de Socket!";
return;
}
forever
{
QDataStream in(socket);
if(blockSize == 0)
{
if(socket->bytesAvailable() )
{
qDebug() << "Erreur < sizeof(quint32))";
return;
}
in >> blockSize;
}
if(socket->bytesAvailable() < blockSize)
{
qDebug() << "données pas arriver en entier";
return;
}
qDebug() << "!!!!!!";
QByteArray dataOut;
QString nameFile;
in >> nameFile >> dataOut;
QFile fileOut(nameFile);
fileOut.open(QIODevice::WriteOnly);
fileOut.write(dataOut);
fileOut.close();
blockSize = 0;
}
}
void FenServeur::deconnexionClient()
{
envoyerATous(tr("<em>Un client vient de se déconnecter</em>"));
// On détermine quel client se déconnecte
QTcpSocket *socket = qobject_cast<QTcpSocket *>(sender());
if (socket == 0) // Si par hasard on n'a pas trouvé le client à l'origine du signal, on arrête la méthode
return;
clients.removeOne(socket);
socket->deleteLater();
}
void FenServeur::envoyerATous(const QString &message)
{
// Préparation du paquet
QByteArray paquet;
QDataStream out(&paquet, QIODevice::WriteOnly);
out << (quint16) 0; // On écrit 0 au début du paquet pour réserver la place pour écrire la taille
out << message; // On ajoute le message à la suite
out.device()->seek(0); // On se replace au début du paquet
out << (quint16) (paquet.size() - sizeof(quint16)); // On écrase le 0 qu'on avait réservé par la longueur du message
// Envoi du paquet préparé à tous les clients connectés au serveur
for (int i = 0; i < clients.size(); i++)
{
clients[i]->write(paquet);
}
} |
merci de me corriger.