Vous êtes sur la page 1sur 8

Initiation au dveloppement Qt sur les sockets

Philippe Latu

philippe.latu(at)inetdoc.net
http://www.inetdoc.net
Rsum

Ce support est la suite de l'initiation au dveloppement en Langage C sur les sockets. L'objectif est nouveau le mme ;
utiliser un code minimaliste accessible aux dbutants. Les bibliothques Qt prsentent un grand intrt lorsque l'on
souhaite produire du code indpendant du systme d'exploitation sous-jacent. On aborde aussi la programmation oriente
objet avec ces bibliothques.

Table des matires


1. Copyright et Licence .................................................................................................................................
1.1. Meta-information ...........................................................................................................................
2. Contexte de dveloppement ........................................................................................................................
2.1. Bibliothques Qt .............................................................................................................................
2.2. Instructions d'excution ...................................................................................................................
2.3. Bibliothques utilises .....................................................................................................................
3. Programme serveur UDP en mode console ....................................................................................................
3.1. Utilisation des sockets avec le serveur UDP console ..............................................................................
3.2. Code source complet .......................................................................................................................
4. Programme serveur UDP en mode graphique .................................................................................................
4.1. Utilisation des sockets avec le serveur UDP graphique ...........................................................................
4.2. Traitement des vnements et des datagrammes ..................................................................................
5. Documents de rfrence ............................................................................................................................

1
1
2
2
2
3
4
4
5
6
6
7
8

1.Copyright et Licence
Copyright (c) 2000,2015 Philippe Latu.
Permission is granted to copy, distribute and/or modify this document under the
terms of the GNU Free Documentation License, Version 1.3 or any later version
published by the Free Software Foundation; with no Invariant Sections, no
Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included
in the section entitled "GNU Free Documentation License".
Copyright (c) 2000,2015 Philippe Latu.
Permission est accorde de copier, distribuer et/ou modifier ce document selon
les termes de la Licence de Documentation Libre GNU (GNU Free Documentation
License), version 1.3 ou toute version ultrieure publie par la Free Software
Foundation ; sans Sections Invariables ; sans Texte de Premire de Couverture,
et sans Texte de Quatrime de Couverture. Une copie de la prsente Licence est
incluse dans la section intitule Licence de Documentation Libre GNU .

1.1.Meta-information
Cet article est crit avec DocBook1 XML sur un systme Debian GNU/Linux2. Il est disponible en version imprimable au format
PDF : socket-qt.pdf3.

1
2
3

http://www.docbook.org
http://www.debian.org
http://www.inetdoc.net/pdf/socket-qt.pdf

Initiation au dveloppement Qt sur les sockets

Initiation au dveloppement Qt sur les sockets

2.Contexte de dveloppement
Comme ce support est la suite de celui sur le Langage C, on reprend le mme dcoupage en deux programmes distincts :
un serveur et un client qui changent des chanes de caractres. la diffrence du support prcdent, on ne prsente pas
le code des deux programmes. Dans le but de limiter le volume du document, on introduit uniquement le code de la partie
serveur qui reoit le message, le traite et le rexpdie au client. Pour les tests, on peut trs bien rutiliser le programme client
dj dvelopp en Langage C : Code du programme udp-client.c4
Le principe d'illustration des communications rseau reste le mme : le client ou talker met un message que le serveur ou
listener traite et retransmet vers le client. Le traitement est toujours aussi minimaliste ; le serveur convertit la chane de
caractres en majuscules.

2.1.Bibliothques Qt
Le diagramme ci-dessous prsente l'architecture des bibliothques Qt. Il met en vidence l'indpendance entre les
dveloppements et les systmes d'exploitation cibles.

Dans notre contexte, on utilise le Langage C++ et l'environnement de dveloppement intgr QtCreator. Cet environnement
comprend les bibliothques Qt rseau dont nous avons besoin.
On se propose de dvelopper le programme serveur en deux temps.
Une version sans graphisme mettant en vidence les appels de bibliothques propres l'utilisation des sockets.
Une version avec une fentre graphique dans laquelle on afche les messages reus depuis un programme client ainsi que
l'adresse IP et le numro de port utiliss par ce programme client.

2.2.Instructions d'excution
On excute le programme client dj dvelopp en Langage C dans un Shell alors que le programme serveur est gr
directement par l'environnement QtCreator. On peut excuter ces deux programmes sur le mme hte en utilisant l'interface
de boucle locale pour les communications rseau.

http://www.inetdoc.net/dev/socket-c/socket-c.udp.client.html#socket-c.udp.client.source

Initiation au dveloppement Qt sur les sockets

Initiation au dveloppement Qt sur les sockets


Le programme serveur, nogui-udp-listener

Note

Dplacer le pointeur de la souris sur l'image, clicker sur le bouton droit et lancer Afcher l'image pour lire
les messages.
C'est dans la partie infrieure droite de la copie d'cran que l'on retrouve en rouge les messages changs entre les
programmes client et serveur. Le code utilis ici correspond la version sans graphisme du programme serveur.
Le programme client, udp-talker.o
$ ./udp-talker.o
Entrez le nom du serveur ou son adresse IP :
127.0.0.1
Entrez le numro de port du serveur :
8888
Entrez quelques caractres au clavier.
Le serveur les modifiera et les renverra.
Pour sortir, entrez une ligne avec le caractre '.' uniquement.
Si une ligne dpasse 100 caractres,
seuls les 100 premiers caractres seront utiliss.
Saisie du message :
texte de test avec tabulation et espaces
Message trait : TEXTE DE TEST AVEC TABULATION ET ESPACES
Saisie du message :
_exit_
Message trait : _EXIT_
Saisie du message :
serveur arrt
Pas de rponse dans la seconde.
Saisie du message :
.

Lorsque le programme serveur est en cours d'excution, il est possible de visualiser la correspondance entre le processus en
cours d'excution et le numro de port en coute l'aide de la commande netstat.
$ netstat -aup | grep -e Proto -e 8888
(Tous les processus ne peuvent tre identifis, les infos sur les processus
non possds ne seront pas affiches, vous devez tre root pour les voir toutes.)
Proto Recv-Q Send-Q Adresse locale
Adresse distante Etat PID/Program name
udp
0
0 *:8888
*:*
3321/QtCreator_UDP

Dans l'exemple ci-dessus, le numro de port 8888 apparat dans la colonne Adresse locale et processus numro 3321
correspond bien au programme QtCreator_UDP_receiver dans la colonne PID/Program name.

2.3.Bibliothques utilises
Les bibliothques standards du Langage C utilises par le programme client sont prsentes dans le document Initiation au
dveloppement C sur les sockets5. On ne s'intresse ici qu' l'utilisation de la brique rseau des bibliothques Qt.

http://www.inetdoc.net/dev/socket-c/

Initiation au dveloppement Qt sur les sockets

Initiation au dveloppement Qt sur les sockets

bind

Cette mthode de la classe QUdpSocket assure la liaison d'un socket avec les adresses et le numro de port spcis.

waitForReadyRead

C'est une fonction bloquante qui attend que de nouvelles donnes soient disponibles en lecture et que le signal
readyRead() ait t mis. Le blocage expire aprs msecs millisecondes. La valeur par dfaut est 30000 millisecondes.
La fonction retourne la valeur boolenne vrai si le signal readyRead() est mis.

readDatagram

Cette fonction assure la rception d'un datagramme de taille infrieure maxSize octets et le stocke dans le tableau data.
L'adresse et le numro de port de l'metteur sont stockes dans les pointeurs *address et *port ( moins que les pointeurs
aient une valeur nulle).
Si maxSize est trop petit, le reste du datagramme est perdu. Pour viter les pertes de donnes, on fait appel
pendingDatagramSize() pour dterminer la taille du datagramme en attente avant d'essayer de le lire. Si maxSize vaut 0,
le datagramme sera limin.

writeDatagram

Cette fonction assure l'mission d'un datagramme de taille size destination de l'adresse address et du port port. Elle
renvoie le nombre d'octets mis avec succs ou -1 en cas d'erreur.
Les datagrammes sont toujours crits en un bloc. La taille maximum d'un datagramme dpend beaucoup du systme
utilis. Elle peut atteindre 8192 octets. Si le datagramme est trop grand, la fonction renvoie -1 et la fonction error()
renvoie DatagramTooLargeError. Il est dconseill d'mettre des datagrammes de plus de 512 octets est en gnral. Mme
s'ils sont mis avec succs, ils seront probablement fragments au niveau de la couche IP avant d'arriver leur destination
nale.

3.Programme serveur UDP en mode console


Avec l'environnement intgr de dveloppement QtCreator, il est possible de crer une application en mode console.
partir de l'cran d'accueil, il faut crer un nouveau projet et choisir Qt Console Application dans la catgorie Application.
L'intrt de cette tape est de produire un chier source unique de taille rduite dans lequel on trouve l'ensemble des appels
de bibliothques Qt.

3.1.Utilisation des sockets avec le serveur UDP console


Avec les bibliothques Qt, on retrouve les lments classiques de reprsentation des communications rseau.
QUdpSocket listenSocket;
QByteArray datagram;
QHostAddress senderAddress;
quint16 senderPort;

listenSocket
Objet de la classe QUdpSocket constituant le canal de communication entre le sous-systme rseau du noyau du systme
d'exploitation et l'application.
datagram
Objet de la classe QByteArray contenant les donnes vues de la couche application de la modlisation rseau.
senderAddress
Objet de la classe QHostAddress contenant la reprsentation de l'adresse de l'hte qui a mis le datagramme reu par le
serveur.
senderPort
Entier en format court contenant le numro de port utilis par l'hte qui a mis le datagramme reu par le serveur.

Initiation au dveloppement Qt sur les sockets

Initiation au dveloppement Qt sur les sockets


<snipped/>
if (!listenSocket.bind(QHostAddress::Any , 8888 )) {
qDebug("Impossible de crer le socket en coute");
exit(EXIT_FAILURE) ;
}
QHostAddress::Any spcie que le programme est en coute sur toutes les adresses IP des interfaces de l'hte.
L'application est en coute sur le port numro 8888 uniquement.

Le le programme s'interrompt en cas d'erreur. On reprend ici le mme principe que dans les autres programmes crits
en Langage C.
Une fois la liaison en place, le programme attend les datagrammes provenant du client.
<snipped/>
if (listenSocket.waitForReadyRead(100))
{
if (listenSocket.hasPendingDatagrams()) ) {
datagram.resize(listenSocket.pendingDatagramSize());
if (listenSocket.readDatagram(datagram.data(), datagram.size(),
&senderAddress, &senderPort) == -1) {
listenSocket.close();
exit(EXIT_FAILURE);
}
msg = datagram.data();

La mthode waitForReadyRead(100) bloque l'excution du programme pendant 100ms, le temps de dtecter un


vnement de rception de donnes sur le socket en coute.
Si un datagramme est en attente, on procde sa lecture.
On redimensionne le tableau des donnes en fonction de la taille du datagramme reu.
On stocke les donnes du datagramme dans la chane de caractres msg.
Enn, l'mission de datagramme du serveur vers le client utilise la fonction writeDatagram avec un jeu de paramtres
identique l'opration de lecture.

3.2.Code source complet


#include
#include
#include
#include
#include

<iostream>
<QtCore/QCoreApplication>
<QtCore/QTextStream>
<QtCore/QDebug>
<QtNetwork>

int main(int argc, char *argv[])


{
QCoreApplication a(argc, argv);
QUdpSocket listenSocket;
QByteArray datagram;
QHostAddress senderAddress;
quint16 senderPort;
QString msg;
if (!listenSocket.bind(QHostAddress::Any, 8888)) {
qDebug("Impossible de crer le socket en coute");
exit(EXIT_FAILURE);
}
while (1) {
if (listenSocket.waitForReadyRead(100)) {
if (listenSocket.hasPendingDatagrams()) {
datagram.resize(listenSocket.pendingDatagramSize());
if (listenSocket.readDatagram(datagram.data(), datagram.size(),
&senderAddress, &senderPort) == -1) {
listenSocket.close();
exit(EXIT_FAILURE);
}
msg = datagram.data();
qDebug() << "Depuis : " << senderAddress.toString() << ':' << senderPort;
qDebug() << "Message : " << msg;
msg = msg.toUpper();
datagram.clear();
datagram.append(msg);

if (listenSocket.writeDatagram(datagram, senderAddress, senderPort) == -1) {


qDebug("mission du message modifi impossible");
listenSocket.close();
exit(EXIT_FAILURE);
}

if (msg == "_EXIT_") {
listenSocket.close();
exit(EXIT_SUCCESS);

Initiation au dveloppement Qt sur les sockets

Initiation au dveloppement Qt sur les sockets

listenSocket.close();
}

return a.exec();

Note

Le code complet du projet est disponible via le chier nogui-udp-listener.tar.gz6.

4.Programme serveur UDP en mode graphique


Dans cette section, on cre une nouvelle application graphique avec l'environnement intgr de dveloppement QtCreator.
partir de l'cran d'accueil, il faut crer un nouveau projet et choisir Application graphique Qt dans la catgorie Projet Qt
Widget.
Relativement la section prcdente dans laquelle on utilisait un chier source unique de taille limite, on se trouve face
un pr dcoupage des chiers dni par dfaut. Avec cette organisation des sources, la gestion de la fentre graphique est
spare du code proprement dit. Tous les attributs de la fentre utilise sont dcrits dans le chier mainwindow.ui.

4.1.Utilisation des sockets avec le serveur UDP graphique


Puisque cette section est consacre une application graphique, on commence par dcrire le volet interface utilisateur.
Une fois le projet ouvert, on slectionne l'onglet Formulaires puis le chier de description de la fentre graphique
mainwindow.ui.

Note

Dplacer le pointeur de la souris sur l'image, cliquer sur le bouton droit et lancer Afcher l'image pour lire
les messages.
Dans cette fentre, on implante trois objets.
pushButton
L'objet bouton, dont on a chang le texte afch, sert quitter le programme. Le code correspondant l'utilisation du
bouton se trouve dans le chier mainwindow.cpp.
msgLabel
Cet objet champ de texte est utilis pour l'afchage de la chane de caractres msg. C'est lors de la rception d'un nouveau
message que les caractres de ce champ sont modis.
senderLabel
Cet objet champ de texte est utilis pour l'afchage de l'adresse IP et le numro de port de l'metteur du message. Comme
dans le cas prcdent, il faut qu'un nouveau message ait t reu et que l'metteur soit identi pour que ce champ soit
modi.
6

http://www.inetdoc.net/dev/socket-qt/qtcreator/nogui-udp-listener.tar.gz

Initiation au dveloppement Qt sur les sockets

Initiation au dveloppement Qt sur les sockets


En revenant au mode diter, on peut parcourir les diffrents chiers sources du projet.
main.cpp

Le programme principal est complt par dfaut lors de la cration d'un nouveau projet. notre niveau, il n'est pas
ncessaire de le modier. Son seul travail est d'afcher la fentre w de la classe MainWindow avant d'entrer dans la boucle
d'vnements (event loop).

mainwindow.h

Ce chier en-tte contient la dclaration de la classe MainWindow. C'est ce niveau que l'on dbute l'dition de code avec
l'ajout d'une mthode et de plusieurs membres privs. Le mot cl private spcie que seuls les objets de la classe ont
accs ces ressources.
La mthode processPendingDatagrams() contient tous les traitements de rception, de transformation et de r mission
des messages. Cette mthode utilise les membres dclars dans la classe.
On retrouve ici la liste des variables du programme de la section prcdente en plus du pointeur de fentre ui (user
interface) et des deux champs de texte prsents plus haut.
private:
Ui::MainWindow *ui;
QLabel *senderLabel, *msgLabel;
QUdpSocket *listenSocket;
QHostAddress senderAddress;
quint16 senderPort;
QString msg;

mainwindow.cpp

Aprs les dclarations des membres et des mthodes de la classe MainWindow, ce chier contient le code des mthodes.
Les points importants ici sont le traitement des vnements et le traitement des datagrammes rseau.

4.2.Traitement des vnements et des datagrammes


Dans ce programme, deux types d'vnements sont scruts : l'arrive d'un nouveau datagramme et le clic sur le bouton Quitter.
Le code correspondant la scrutation des vnements est dcrit dans la mthode MainWindow du chier mainwindow.cpp.
<snipped/>
QObject::connect(listenSocket, SIGNAL(readyRead()),
this, SLOT(processPendingDatagrams()));
QObject::connect(ui->pushButton, SIGNAL(clicked()),
this, SLOT(close()));

L'appel de la mthode connect() de la classe QObject cre une connexion entre le socket listenSocket et le signal issu
de la mthode readyRead().
Ds qu'un signal est reu par la mthode connect(), un datagramme est en attente de lecture. Cette lecture et le
traitement associ sont effectus l'aide du sous-programme processPendingDatagrams() dont le code est donn dans
le mme chier source.
Ici, l'appel la mthode connect() de la classe QObject cre une connexion entre l'objet pushButton et le signal issu de la
mthode clicked(). Ds que ce signal est reu, la mthode close() entrane la n d'excution du programme.
Pour le traitement des datagrammes, c'est le code du sous-programme processPendingDatagrams() qui assure la lecture,
le passage en majuscules des caractres de la chane et la rmission. L'opration de transformation des caractres en
majuscules n'est qu'une illustration d'un traitement possible. Comme la plupart des protocoles de l'Internet sont bass sur
l'change de messages sous forme de chanes de caractres, on utilise ici une forme minimaliste de traitement par requte
- rponse.

Initiation au dveloppement Qt sur les sockets

Initiation au dveloppement Qt sur les sockets


<snipped/>
void MainWindow::processPendingDatagrams()
{
while (listenSocket->hasPendingDatagrams())

QByteArray datagram;
datagram.resize(listenSocket->pendingDatagramSize());
if (listenSocket->readDatagram(datagram.data(), datagram.size(),
&senderAddress, &senderPort) == -1) {
listenSocket->close();
exit(EXIT_FAILURE);
}
msg = datagram.data();
qDebug() << "Depuis : " << senderAddress.toString() << ':' << senderPort;
qDebug() << Message : " << msg;
ui->senderLabel->setText(tr("Depuis : %1:%2")
. arg(senderAddress.toString())
. arg(senderPort));
ui->msgLabel->setText(tr("Message : \"%1\"")
. arg(msg));
msg = msg.toUpper();
datagram.clear();
datagram.append(msg);

if (listenSocket->writeDatagram(datagram, senderAddress, senderPort) == -1) {


qDebug("mission du message modifi impossible");
listenSocket->close();
exit(EXIT_FAILURE);
}
}

On retrouve les lments du prcdent programme en mode console dans le code ci-dessus.
La mthode hasPendingDatagrams() renvoie la valeur boolenne vrai tant qu'un datagramme est prsent dans la le
d'attente.
La mthode readDatagram() collecte les donnes du datagramme ainsi que sa provenance en identiant l'adresse de
l'metteur et le numro de port source utilis.
La mthode setText() est appele pour changer le texte rfrenc par l'tiquette senderLabel dans la fentre MainWindow.
On fait apparatre l'adresse IP et le numro de port de l'metteur du message.
La mthode setText() est nouveau appele pour changer le texte rfrenc par l'tiquette msgLabel dans la fentre
MainWindow. On fait apparatre ici le contenu de la chane de caractres reue.
Une fois la chane de caractres transforme, elle est renvoye l'metteur l'aide de la mthode writeDatagram().
Note

Le code complet du projet est disponible via le chier gui-udp-listener.tar.gz7.

5.Documents de rfrence
Qt Network Programming
Qt Network Programming8 : page d'entre dans la documentation en ligne des bibliothques Qt sur les communications
rseau.
Modlisations rseau
Modlisations rseau9 : prsentation et comparaison des modlisations OSI et Internet.
Adressage IPv4
Adressage IPv410 : support complet sur l'adressage du protocole de couche rseau de l'Internet (IP).
Conguration d'une interface rseau
Conguration d'une interface de rseau local11 : support sur la conguration des interfaces rseau. Il permet notamment
de relever les adresses IP des htes en communication.

http://www.inetdoc.net/dev/socket-qt/qtcreator/gui-udp-listener.tar.gz
http://doc.qt.nokia.com/4.7/network-programming.html
http://www.inetdoc.net/articles/modelisation/
10
http://www.inetdoc.net/articles/adressage.ipv4/
11
http://www.inetdoc.net/travaux_pratiques/cong.interface.lan/
8
9

Initiation au dveloppement Qt sur les sockets

Vous aimerez peut-être aussi