Bonjour à tous, je code actuellement un petit tchat pour permettre la communication en réseau local ou sur le WAN. Tout fonctionne bien lorsque je clique sur le bouton 'Envoyer', le client envoie le message au serveur et le serveur renvoie le message a tous les clients, message qui s'affiche dans un QTextBox.
Il reste un petit truc qui va pas (ca doit être tout con mais je le vois pas): Lorsque je clique sur le bouton Confirmer, pour envoyer le pseudo au serveur, je récupère le pseudo mais dans la liste des messages, or je voudrai qu'il aille dans la liste prévue a cet effet...
Voici mon code:
FenClient.h
private slots:
void donneesRecues();
void pseudoRecu();
void confirmation();
private:
quint16 tailleMessage;
quint16 taillePseudo;
FenClient.cpp
FenClient::FenClient()
{
connect(boutonConfirmer, SIGNAL(clicked()), this, SLOT(confirmation()));
}
void FenClient::confirmation()
{
QByteArray paquetPseudo;
QDataStream outPseudo(&paquetPseudo, QIODevice::WriteOnly);
QString pseudoAEnvoyer = tr("<strong>") + pseudo->text();
outPseudo << (quint16) 0;
outPseudo << pseudoAEnvoyer;
outPseudo.device()->seek(0);
outPseudo << (quint16) (paquetPseudo.size() - sizeof(quint16));
socket->write(paquetPseudo); // On envoie le paquet
pseudo->setEnabled(false); // On grise le champs du pseudo
boutonConfirmer->setEnabled(false); //On grise le bouton de confirmation
}
// Envoi d'un message au serveur
void FenClient::on_boutonEnvoyer_clicked()
{
QByteArray paquet;
QDataStream out(&paquet, QIODevice::WriteOnly);
// On prépare le paquet à envoyer
QString messageAEnvoyer = tr("<strong>") + pseudo->text() +tr("</strong> : ") + message->text();
out << (quint16) 0;
out << messageAEnvoyer;
out.device()->seek(0);
out << (quint16) (paquet.size() - sizeof(quint16));
socket->write(paquet); // On envoie le paquet
message->clear(); // On vide la zone d'écriture du message
message->setFocus(); // Et on remet le curseur à l'intérieur
}
void FenClient::pseudoRecu()
{
/* Même principe que lorsque le serveur reçoit un paquet :
On essaie de récupérer la taille du pseudo
Une fois qu'on l'a, on attend d'avoir reçu le pseudo entier (en se basant sur la taille annoncée taillePseudo)
*/
QDataStream inPseudo(socket);
if (taillePseudo == 0)
{
if (socket->bytesAvailable() < (int)sizeof(quint16))
return;
inPseudo >> taillePseudo;
}
if (socket->bytesAvailable() < taillePseudo)
return;
// Si on arrive jusqu'à cette ligne, on peut récupérer le pseudo entier
QString pseudoRecu;
inPseudo >> pseudoRecu;
//On affiche le pseudo sur la zone prévue
listPseudo->append(pseudoRecu);
}
void FenClient::donneesRecues()
{
/* Même principe que lorsque le serveur reçoit un paquet :
On essaie de récupérer la taille du message
Une fois qu'on l'a, on attend d'avoir reçu le message entier (en se basant sur la taille annoncée tailleMessage)
*/
QDataStream in(socket);
if (tailleMessage == 0)
{
if (socket->bytesAvailable() < (int)sizeof(quint16))
return;
in >> tailleMessage;
}
if (socket->bytesAvailable() < tailleMessage)
return;
// Si on arrive jusqu'à cette ligne, on peut récupérer le message entier
QString messageRecu;
in >> messageRecu;
// On affiche le message sur la zone de Chat
listeMessages->append(messageRecu);
// On remet la taille du message à 0 pour pouvoir recevoir de futurs messages
tailleMessage = 0;
}
FenServeur.h
public:
void envoyerATous(const QString &message);
void envoyerPseudoATous(const QString &pseudo);
private:
quint16 tailleMessage;
quint16 taillePseudo;
FenServeur.cpp
//on recoit le pseudo
void FenServeur::pseudoRecu()
{
// 1 : on reçoit un paquet (ou un sous-paquet) d'un des clients
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;
QDataStream inPseudo(socket); // Si tout va bien, on continue : on lit ce que contient la socketPseudo
if (taillePseudo == 0) // Si on ne connaît pas encore la taille du pseudo, on essaie de la récupérer
{
if (socket->bytesAvailable() < (int)sizeof(quint16)) // On n'a pas reçu la taille du pseudo en entier
return;
inPseudo >> taillePseudo; // Si on a reçu la taille du pseudo en entier, on la récupère
}
// Si on connaît la taille du pseudo, on vérifie si on a reçu le message en entier
if (socket->bytesAvailable() < taillePseudo) // Si on n'a pas encore tout reçu, on arrête la méthode
return;
// Si ces lignes s'exécutent, c'est qu'on a reçu tout le pseudo : on peut le récupérer !
QString pseudo;
inPseudo >> pseudo;
// 2 : on renvoie le message à tous les clients
envoyerPseudoATous(pseudo);
}
//On recoit un message
void FenServeur::donneesRecues()
{
// 1 : on reçoit un paquet (ou un sous-paquet) d'un des clients
// On détermine quel client envoie le message (recherche du QTcpSocket du client)
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;
// Si tout va bien, on continue : on récupère le message
QDataStream in(socket);
if (tailleMessage == 0) // Si on ne connaît pas encore la taille du message, on essaie de la récupérer
{
if (socket->bytesAvailable() < (int)sizeof(quint16)) // On n'a pas reçu la taille du message en entier
return;
in >> tailleMessage; // Si on a reçu la taille du message en entier, on la récupère
}
// Si on connaît la taille du message, on vérifie si on a reçu le message en entier
if (socket->bytesAvailable() < tailleMessage) // Si on n'a pas encore tout reçu, on arrête la méthode
return;
// Si ces lignes s'exécutent, c'est qu'on a reçu tout le message : on peut le récupérer !
QString message;
in >> message;
// 2 : on renvoie le message à tous les clients
envoyerATous(message);
// 3 : remise de la taille du message à 0 pour permettre la réception des futurs messages
tailleMessage = 0;
}
//Envoi du pseudo a tous le monde
void FenServeur::envoyerPseudoATous(const QString &pseudo)
{
QByteArray paquetPseudo;
QDataStream outPseudo(&paquetPseudo, QIODevice::WriteOnly);
// Calcul de la taille du pseudo
outPseudo << (quint16) 0;
outPseudo << pseudo;
outPseudo.device()->seek(0);
outPseudo << (quint16) (paquetPseudo.size() - sizeof(quint16));
// Envoi du paquet préparé à tous les clients connectés au serveur
for (int i = 0; i < clients.size(); i++)
{
clients[i]->write(paquetPseudo);
}
}
void FenServeur::envoyerATous(const QString &message)
{
// Préparation du paquet
QByteArray paquet;
QDataStream out(&paquet, QIODevice::WriteOnly);
//Calcul de la taille du paquet
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);
}
}
Voila, je conclu qu'il ne différencie pas l'envoi d'un pseudo de l'envoi d'un message, j'ai essayé pas mal de trucs mais rien ne fonctionne... je sens que c'est très proche!
Une idée??
Merci!