Application client
Création des fichiers
Comme pour l'application Serveur on créé les fichiers initiaux, mais la fenêtre cliente sera réalisée avec QT Designer.
- Création du projet
- Fichier main.cpp
- Fenêtre du client clientwin
Codes sources
Clientwin.pro
TEMPLATE = app
QT += widgets network
SOURCES += \
main.cpp \
clientwin.cpp
FORMS += \
clientwin.ui
HEADERS += \
clientwin.h
Main.cpp
Le main.cpp presque identique au précédent :
#include <QApplication>
#include "clientwin.h"
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
clientwin fenetre;
fenetre.show();
return app.exec();
}
clientwin.h
La fenêtre a été décrite avec QT Designer. Le choix s'est porté sur une fenêtre de Dialogue (QDialog)
#ifndef CLIENTWIN_H
#define CLIENTWIN_H
#include <QDialog>
#include <QtNetwork>
namespace Ui {
class clientwin;
}
class clientwin : public QDialog
{
Q_OBJECT
public:
explicit clientwin(QWidget *parent = 0);
~clientwin();
private slots :
void on_connexionBtn_clicked(); // slot de gestion du bouton de connexion
void on_sendBtn_clicked(); //slot de gestion du bouton d'émission de message
void on_dataLE_returnPressed(); //slot de gestion de la touche Entrée pour le champ de saisie
void getserverdata(); // en provenance de la socket, lit la socket et inscrit l'information
void connecte();
void deconnecte();
void erreurSocket(QAbstractSocket::SocketError erreur);
private:
Ui::clientwin *ui; //fenêtre IHM
QTcpSocket *socket;
quint16 tailleMessage;
};
#endif // CLIENTWIN_H
clientwin.cpp
Le fonctionnement est sensiblement le même que pour le serveur
#include "clientwin.h"
#include "ui_clientwin.h"
clientwin::clientwin(QWidget *parent) :
QDialog(parent),
ui(new Ui::clientwin)
{
ui->setupUi(this);
socket = new QTcpSocket(this); //créé l'instance de QTcpSocket
connect(socket, SIGNAL(readyRead()), this, SLOT(getserverdata()));//gestion de la donnée serveur
connect(socket, SIGNAL(connected()), this, SLOT(connecte())); //gestion de signal de connexion
connect(socket, SIGNAL(disconnected()), this, SLOT(deconnecte())); //gestion de signal de déconnexion
connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(erreurSocket(QAbstractSocket::SocketError)));//gestion de signal d'erreur
tailleMessage = 0;
}
clientwin::~clientwin()
{
delete ui;
}
//**************** Slot de connexion **********************************************************
void clientwin::connecte()
{ //lorsque le signal de connexion est reçu du serveur le client affiche un message et les paramétrages
//ne peuvent plus être modifiés
ui->messageTE ->append(tr("<em>Connexion réussie !</em>"));
ui->connexionBtn->setEnabled(false);
ui->adresseEdit->setEnabled(false);
ui->portSB->setEnabled(false);
}
//****** Ce qui se passe quand on appuie sur le bouton Connexion ******************************
void clientwin::on_connexionBtn_clicked()
{//l'utilisateur a cliqué sur le bouton de connexion
ui->messageTE->append("Tentative de connexion ! "); //on ecrit ce qui se passe
ui->connexionBtn->setEnabled(false); //on évite les multiclics en dévalidant le bouton
socket->abort(); //on désactive les connexions précédentes
socket->connectToHost(ui->adresseEdit->text(), ui->portSB->value());//on se connecte
}
//****** Ce qui se passe quand on appuie sur le bouton envoyer ******************************
void clientwin::on_sendBtn_clicked()
{//l'utilisateur a cliqué sur le bouton envoyer au serveur
QByteArray paquet;
QDataStream out(&paquet, QIODevice::WriteOnly);
QString DonneesAEnvoyer = ui->dataLE->text();
out<<(quint16) 0; //on réserve l'entete pour la taille des données
out<<DonneesAEnvoyer;//on ajoute la donnée
out.device()->seek(0);//on retourne au début
out<<(quint16)(paquet.size() - sizeof(quint16));
socket->write(paquet); //on écrit la donnée sur le socket
ui->dataLE->clear();//on efface le message initial
ui->dataLE->focusWidget() ;//et on redonne le focus à la ligne d'édition
}
// Appuyer sur la touche Entrée a le même effet que cliquer sur le bouton "Envoyer"
void clientwin::on_dataLE_returnPressed()
{
on_sendBtn_clicked();
}
//****** Ce qui se passe quand une donnée arrive *********************************************
void clientwin::getserverdata()
{ // Affiche les données reçues par le serveur
QDataStream in(socket);
if (tailleMessage == 0)
{//taille non recupérée
if (socket->bytesAvailable() < (int)sizeof(quint16))
return;
in >> tailleMessage;
}
if (socket->bytesAvailable() < tailleMessage)
return;
// On a toutes les infos nécessaires pour le message
QString message;
in >> message;
// On affiche le message chez le client
ui->messageTE->append(message);
// On remet la taille du message à 0 pour pouvoir recevoir de futurs messages
tailleMessage = 0;
}
//**************** Gestion des erreurs de transmission *****************************************************
void clientwin::erreurSocket(QAbstractSocket::SocketError erreur)
{
switch(erreur) // On affiche un message différent selon l'erreur qu'on nous indique
{
case QAbstractSocket::HostNotFoundError:
ui->messageTE->append(tr("<em>ERREUR : le serveur n'a pas pu être trouvé. Vérifiez l'IP et le port.</em>"));
break;
case QAbstractSocket::ConnectionRefusedError:
ui->messageTE->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:
ui->messageTE->append(tr("<em>ERREUR : le serveur a coupé la connexion.</em>"));
break;
default:
ui->messageTE->append(tr("<em>ERREUR : ") + socket->errorString() + tr("</em>"));
}
ui->connexionBtn->setEnabled(true);
}
//*************** Affiche me message de déconnexion lorsque le serveur a déconnecté le client
void clientwin::deconnecte()
{
ui->messageTE ->append(tr("<em>Déconnecté du serveur</em>"));
ui->connexionBtn->setEnabled(true);
ui->adresseEdit->setEnabled(true);
ui->portSB->setEnabled(true);
}