Você está na página 1de 4

Programmation rseau en Python page 1 de 4

Programmation rseau en Python


Sockets

I) Faire communiquer des programmes II) Systme dadressage TCP/IP


Voici le problme rsoudre : 1) Adresses IP et noms : associs aux ordinateurs
On dispose de deux ordinateurs A et B, tous deux connects un rseau local. Le cas Les adresses IP sont attribues par les systmes dexploitation des ordinateurs (Win-
le plus simple est celui o les deux ordinateurs sont simplement relis par un cble dows, Mac OS, Unix), soit automatiquement, soit daprs une configuration fournie par
Ethernet. ladministrateur du rseau. Cela se produit quand les ordinateurs sont installs dans le
On veut crire un programme "client.py" tournant sur lordinateur A et capable de rseau et mis en route. Le systme dexploitation se dbrouille pour que chaque ordina-
demander un service un programme "serveur.py" tournant sur lordinateur B, pro- teur du rseau ait une adresse IP distincte.
gramme lui-mme capable de rpondre ce service. Une fois cela fait, chaque ordinateur est capable de dire quelle est son adresse IP. Dans
un programme Python, pour savoir quelle est ladresse de lordinateur (de lhte), on
Prenons comme exemple un service minimal. Le client enverra un texte, par exemple
peut excuter linstruction suivante :
"bonjour", et le serveur rpondra "bien reu : " suivi du texte reu, donc ici : "bien
adresse = socket.gethostbyname(socket.gethostname())
reu : bonjour". Et cest tout.
On est oblig de combiner deux fonctions : lune qui donne le "nom" de lor-
Pour raliser cela, il faut dabord se demander comment est organis le rseau, suivant dinateur (socket.gethostname()) et lautre qui convertit le nom en adresse
quelles conventions et quels standards. Ici, nous supposerons un cas extrmement usuel : (socket.gethostbyname(...)).
le rseau obit au standard TCP/IP. Il sagit dun recueil de conventions et de rgles Ces deux fonctions ne sont pas disponibles dans le noyau Python, il faut importer le
quon appelle un protocole, ici Transport Control Protocol / Internet Protocol. Cest le module socket pour pouvoir les utiliser : import socket
standard utilis sur Internet, et il a t dfini il y a une trentaine dannes.
Le nom de lordinateur est affect lui aussi par le systme dexploitation daprs une
Dans ce standard, chaque ordinateur reli au rseau (on dit un "poste" ou un "hte") configuration fournie par ladministrateur du rseau. Il est effectivement plus facile pour
est identifi par une adresse IP au format xxx.xxx.xxx.xxx, par exemple 192.168.0.100. un programmeur de dsigner lordinateur par un nom significatif, comme "ordiDuDi-
Et chaque programme tournant sur un hte et souhaitant communiquer par le rseau recteur" plutt que par une adresse 192.168.0.100. Le systme se charge de convertir les
est identifi par un nombre entier de 0 65535, quon appelle un port. noms en adresses et inversement. Mais lorsque des messages sont changs sur le rseau,
Lchange entre le client et le serveur ressemblera alors ce qui suit : seules les adresses interviennent.
de (98.76.54.321, 50321)
(123.45.67.89, 50000) : Vous me recevez ?
de (123.45.67.89, 50000)
(98.76.54.321, 50321) : Oui. Et vous, vous me recevez ? 2) Ports : associs aux programmes
de (98.76.54.321, 50321)
(123.45.67.89, 50000) : Oui
de (98.76.54.321, 50321)
(123.45.67.89, 50000) : Jenvoie le texte "bonjour" Le choix dun numro de port identifiant un programme est linitiative du program-
de (123.45.67.89, (98.76.54.321, 50321) : Jenvoie le texte "bien reu : bon- meur. Mais il peut le faire de deux faons : soit il fixe lui-mme une valeur pour le port
50000)
jour". (en vrifiant que le port quil choisit nest pas utilis par un autre programme), soit il
demande au systme dexploitation un port libre.
98.76.54.321 est ladresse de lordinateur A, 123.45.67.89 est ladresse de lordinateur B.
Certains numros de ports sont rservs de manire standard certains types de pro-
50321 est le port du programme client.py, 50000 celui du programme serveur.py. grammes : par exemple le port 80 est rserv un serveur web utilisant le protocole
Mais comment, quand et par qui sont attribus les ports et les adresses ? HTTP, le port 21 est rserv un serveur de fichiers utilisant le protocole FTP.
Programmation rseau en Python page 2 de 4

Si on veut programmer un serveur en dehors des protocoles standards, il faut choisir un Pour pouvoir crire cela, le programmeur client doit connatre ladresse et le port du
numro de port suffisamment grand, par exemple suprieur 10000. serveur.
Cette instruction fait plusieurs choses :
elle demande au systme dexploitation ladresse IP de lordinateur local et un port
III) Programmation libre pour pouvoir communiquer. Ces deux informations sont stockes dans s.
elle stocke aussi dans s ladresse et le port du serveur
1) Les sockets Python elle envoie sur le rseau un message au serveur de type particulier appel "demande
de synchronisation".
Une fois les ordinateurs en rseau, et les deux programmes lancs, comment peuvent-ils
communiquer par lintermdiaire dinstructions Python ? Elle attend ensuite que les systmes dexploitation local et distant se synchronisent,
cest--dire vrifient que les communications entre les deux fonctionnent bien dans les
Le mcanisme de base sappelle socket. "socket" est un mot anglais signifiant "prise", ici
deux sens.
plutt prise tlphonique murale, o lon branche un tlphone pour pouvoir commu-
niquer. En Python, ce mot est utilis comme mtaphore pour dsigner un mcanisme Cette synchronisation peut chouer (par exemple si le serveur nest pas en tat de
purement logiciel dont la fonction ressemble celle dune prise tlphonique. fonctionnement), auquel cas le programme client finit par afficher un message derreur.
Dans le contexte informatique, comme cest un mot technique il nest quasiment jamais Lorsquelle russit, le programme client peut continuer aprs lappel de la fonction
traduit. Son genre (masculin ou fminin) na pas lair trs dtermin et varie suivant les connect. Il est alors assur quil pourra communiquer avec le serveur en utilisant le
textes. Nous dirons ici "un socket". socket (du moins avec le genre dassurance quon peut avoir sur un rseau, o les inci-
En termes de programmation, un socket est dabord un objet logiciel, au sens de la dents sont toujours possibles).
programmation "oriente objet". Un tel objet mmorise des donnes, comme le ferait
une liste, mais possde aussi des fonctions. Si x est un objet et f une fonction possde 3) Initialisation dun socket par le programme serveur
par x, lappel de cette fonction scrit x.f().
Un socket utilis dans un programme mmorise essentiellement des paramtres nces- Les rles du serveur et du client ne sont pas symtriques : le serveur est un fournisseur,
saires une communication par le rseau entre deux interlocuteurs : le programme local alors que le client est un consommateur. Le serveur, une fois lanc, doit attendre que
qui utilise le socket et le programme distant avec lequel on communique. Les paramtres des clients sadressent lui, et il les sert les uns aprs les autres (dans le cas le plus
sont ladresse de lhte local, le port du programme local, ladresse de lhte distant et simple).
le port du programme distant. Le serveur doit donc commencer par mettre en place un mcanisme dattente de de-
Les fonctions dun socket ont pour but dune part de configurer ces paramtres ou de mandes de connexion.
les consulter et dautre part deffectuer des oprations de communication sur le rseau. Cela seffectue par un socket, qui sera initialis dune manire diffrente de celle du
client.
Le serveur commence par crer un socket, comme le client :
2) Initialisation dun socket par le programme client s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
Lutilisation dun socket par le client est plus simple que par le serveur, cest pourquoi Puis il stocke dans ce socket son adresse et son port, on appelle cela lier le socket :
nous commenons par le client. socket.bind(adresseServeur, portServeur)
Le client doit dabord crer un socket : Puis il met le socket en mode dcoute des demandes de clients (on dit aussi en mode
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) passif ) :
socket.AF_INET et socket.SOCK_STREAM sont des constantes dfinies par Python et s.listen()
indiquent le type du protocole souhait. Ici, on veut dire en gros quon va utiliser le Cela veut dire quil sadresse au systme dexploitation en lui disant quil souhaite
protocole TCP/IP. recevoir les demandes de synchronisation dans une zone mmoire alloue pour cela et
Une fois cette instruction excute, on obtient un objet socket s vide. qui sera gre comme une file dattente
Ensuite, il faut le configurer et envoyer sur le rseau une demande de connexion au Il se met ensuite en attente de ces demandes :
serveur. c = s.accept() Cette instruction fonctionne de la manire suivante :
Cela se fait par s.connect((adresseServeur, portServeur)), par exemple sil y a des demandes dans la file dattente, il prend la premire, ce qui a pour effet
s.connect((192.168.0.100, 50000)). daccepter cette demande.
Programmation rseau en Python page 3 de 4

sil ny en a pas, le programme attend la premire qui arrive pour la prendre et Mais alors cela complique les choses pour le moindre envoi de donnes, car il faut tenir
laccepter compte de cette incertitude et faire une boucle dessais successifs.
une fois une demande accepte, il cre un nouveau socket c pour communiquer avec le Sauf . . . si vous utilisez sendall au lieu de send. Cest une fonction qui nest pas
client. Ce socket est configur avec les paramtres suivants : adresse et port du serveur, standard dans le mcanisme des sockets mais que Python a rajoute pour faciliter la
adresse et port du client (le serveur connat ces informations car elles figurent dans vie des dveloppeurs. Avec sendall, vous tes certain que toutes vos donnes ont t
la demande) transmises. Enfin, "certain", cest vite dit . . .. A part lengorgement, il peut aussi y avoir
Un serveur est cens fonctionner en permanence, et cette attente peut ventuellement des erreurs logicielles ou matrielles sur le rseau, quon ne peut pas toujours rattaper.
durer longtemps. Elle bloque le programme serveur. Par la suite, nous utiliserons sendall plutt que send.
Le nouveau socket c est dans un tat analogue au socket du client : ils peuvent servir
tous les deux communiquer entre les deux interlocuteurs bien dfinis. On dit quils
sont tous les deux dans un tat "connect". 4).2 Rception : recv

Pour recevoir des donnes, on utilise la fonction recv. Elle admet un argument, qui est
4) Utilisation dun socket pour communiquer la taille des donnes quon souhaite recevoir (en nombre doctets), et elle rend ce quelle
a reu (une chane de caractres). Par exemple, linstruction resultat = s.recv(4)
Lorsquun socket s est dans l"tat connect, on peut lutiliser pour envoyer des donnes pourra renvoyer resultat = "abcd".
(une chane de caractres) par s.send(donnes) ou s.sendall(donnes) et en recevoir
Mais comment a, "la taille que je souhaite recevoir" ? Je ne souhaite rien du tout ! Cela
dune taille maximale tailleMax par message = s.recv(tailleMax)
dpend de ce que menvoie mon interlocuteur, et cest en gnral imprvisible ! Ny a-t-il
Dans les fonctions send, sendall et recv, le programme na plus spcifier les adresses
pas moyen de dire : "recevoir le message entier que ma envoy mon interlocuteur" ?
et les ports, car ceux-ci sont mmoriss dans le socket. Cest la fois une facilit et une
Non, ce nest pas possible au niveau lmentaire des sockets. Ici encore, on doit tenir
scurit : dabord on na pas rcrire ces adresses et ports chaque fois, et ensuite
compte des limitations dun rseau : on ne peut pas allouer des capacits illimites,
cela permet de filtrer les messages pour ne conserver que ceux qui concernent le bon
surtout pour des rseaux gigantesques comme Internet. Les tailles des "botes denvoi"
client et le bon serveur.
et "botes de rception" doivent tre limites.
Cest cause de cette limitation des tailles que le rseau peut ralentir : lorsque votre
4).1 Envoi : send et sendall bote de rception est pleine, il attend que vous retiriez des donnes pour continuer
Le manuel Python indique que linstruction s.send(donnes) envoie les donnes par le pouvoir vous en envoyer, ce qui bloque lmetteur lautre bout.
socket s. Mais si on sarrte cette dfinition, on passe ct de beaucoup de difficults Dautre part, au niveau des sockets, le concept de "message entier qui forme un tout"
potentielles. nexiste pas. Les tre humains sont habitus utiliser diffrents procds pour frac-
Une dfinition plus juste serait de dire que send essaye denvoyer autant de don- tionner leurs communications en units conceptuelles (des phrases, des messages), par
nes quelle peut, et quelle vous avertit en retour combien elle a pu en envoyer. exemple en faisant des pauses entre les diffrents messages. Ici ce nest pas le cas.
send est une fonction qui rend un rsultat : le nombre doctets (bytes) transmis : Ce nest pas parce quun metteur envoie sendall("abcd") puis aprs une pause
nombre = s.send(donnes). sendall("efg") que le rcepteur comprendra quil sagit de deux messages bien s-
Par exemple, si linstruction nombre = s.send("abcd") retourne nombre = 2, cest que pars.
le socket na pu envoyer que les deux premiers caractres "ab". Il reste les deux suivants La ralit du rseau vu par les sockets, cest que la transmission est un flux (stream) de
"cd", et il est de votre responsabilit de continuer essayer de les envoyer jusqu ce caractres : on envoie un "a", puis un "b", puis un "c", puis un "d", puis un "e", puis
que cela russisse. Il ny a aucun automatisme qui le fera pour vous. un "f", puis un "g". Il ny a pas de marque de sparation dans ce flux entre "abcd" et
On rencontre ici un comportement un peu inhabituel par rapport la programmation "efg". Aprs ces deux sendall, si la bote de rception du rcepteur tait vide avant et
classique : une fonction qui peut chouer, ou chouer en partie, de manire imprvi- si elle est assez grande, elle contiendra "abcdefg". Dans cet tat, si le rcepteur excute
sible. Cela est du aux particularits dun rseau : certains mcanismes ont des capacits la fonction recv(5), il obtiendra comme rsultat "abcde", et il ne verra pas quil y a
limites, et lorsque le rseau est trs encombr on ne peut pas toujours transmettre ins- eu deux envois spars "abcd" et "efg". La bote de rception contiendra alors ce qui
tantanment tout ce quon voudrait transmettre. Alors, pour ne pas bloquer le rseau reste "fg".
on nattend pas indfiniment mais on abandonne au bout dun certain temps (timeout) Donc pour bien comprendre la fonction recv(k), il faut tre conscient de ces phno-
et on ne transmet quune partie des donnes. mnes :
Programmation rseau en Python page 4 de 4

la transmission par un socket est un flux de caractres, sans marque distinctive entre retourne alors une chane vide, ce qui ne serait pas possible si le socket tait encore
les diffrents envois effectus par sendall ouvert (le rcepteur attendrait). La rception dune chane vide signale la fermeture
ce flux arrive dans la bote denvoi du rcepteur, qui est gre par le systme dex- du socket de lmetteur.
ploitation. On ne connat pas sa capacit a priori, cela dpend du systme. Si la bote Dans tous les cas, larrive du message peut se faire en plusieurs fois. Le rcepteur doit
est pleine, le flux est bloqu en attente chez lmetteur. faire une boucle avec des recv et accumuler ce quil reoit jusqu ce que le critre
le programme Python qui veut lire sa bote de rception ne peut le faire quen spci- permettant de reconnatre un message complet soit satisfait.
fiant le nombre de caractres quil veut retirer (k). Diffrents cas se prsentent alors : On voit combien le mcanisme des sockets est lmentaire : il ne suffit pas tout
si la bote est vide, le programme se met en attente et attend que des donnes rgler, il y a encore du travail faire pour raliser des applications de communication
arrivent satisfaisantes.
si la bote contient au moins k caractres, la fonction recv prend les k premiers et Heureusement, la plupart des types importants dapplication ont t tudis et raliss
laisse les autres dans la bote. sous forme de modules Python : HTTP, FTP, etc.
si la bote contient moins de k caractres (mais pas 0), elle prend ce quil y a et
laisse la bote vide
IV) Conclusion
4).3 Protocole Commandant, ici lofficier des transmissions, nous venons de recevoir un message :
On voit que le mcanisme des sockets se place un niveau technique lmentaire (flux "Vous avez ordre de tirer vos missiles nuclaires. Cest la Fin"
de caractres indiffrencis, retrait dun nombre donn de caractres dans une bote de Avis tout lquipage, cest votre commandant qui vous parle ! Nous avons ordre de
capacit limite), comment alors obtenir une communication o on pourrait distinguer tirer nos missiles nuclaires. Nous allons accomplir cette mission. Attention, 5, 4, 3,
des units conceptuelles identifiables quon pourrait appeler des "messages" ? Comment 2, 1, 0 ... Missiles lancs ! Messieurs, la troisime guerre mondiale est commence !
les sparer lenvoi et comment les reconstituer la rception ? Euh, commandant ...
Ce problme est appel framing en anglais. Le mot frame veut dire "cadre". La question Oui, officier ?
est de savoir comment encadrer votre message lenvoi pour quil soit reconnu comme On avait convenu avec mon collgue terre quil ferait des sendall sur son socket
un tout la rception. avec des contenus de moins de 1024 caractres et que moi je ferais des recv sur mon
Rponse : en dfinissant un protocole au niveau de lapplication et en mettant en place socket en prenant 1024 caractres.
les mcanismes de vrification et dutilisation ncessaires ce protocole. Cest ce que Et alors ?
font les applications usuelles qui utilisent les sockets, comme par exemple un navigateur Eh bien, a nous semblait bon comme protocole, il envoie un message court par
web, qui utilise le protocole HTTP, ou une serveur de fichiers, qui utilise le protocole sendall et je le rcupre en une fois par recv(1024). Et en plus, il termine ses
FTP. messages par "Cest la Fin", comme a on est surs davoir le message entier. Mais je
Que serait un protocole qui permettrait un change de messages entre le client et le ne comprends pas ce qui sest pass ...
serveur ? Il y a plusieurs ides possibles pour arriver dlimiter les messages : Que sest-il pass ?
Nenvoyer que des messages ayant une taille fixe t, et retirer la rception t caractres Eh bien je viens de recevoir la suite du message ...
chaque fois. Quand on en a reu exactement t, on est certain davoir reu un message Il y a une suite ?
complet. Oui, je ne comprends pas : "lande qui vous prviendra si la Russie attaque, mais pour
Ajouter au dbut de chaque message une marque spciale de dbut de message, et la linstant il ny a pas de danger, ne faites rien. Cest la Fin".
fin une marque de fin. Cela suppose que le rcepteur effectue une analyse syntaxique Quoi "lande" ? Ah oui, "cest la Finlande qui vous prviendra". Ca cest amusant !
de ce quil reoit. Amusant ? ? ?
Faire prcder chaque message de sa taille (crite sur un nombre fixe de caractres Oui, son sendall a envoy en deux fois, et "Cest la Finlande" a t coup en "Cest
pour simplifier). Le rcepteur sait alors exactement combien de caractres il doit la Fin" et "lande". Et le vrai "Cest la Fin" est venu aprs. Cest trop drle, il va
retirer. bien rire quand il va apprendre a !
Plus radicalement, nutiliser un socket que pour un seul envoi et une seule rception, Officier ?
et fermer le socket ensuite. Lorsquun metteur ferme un socket, le rcepteur finit Oui, mon commandant ?
par sen apercevoir quand il ny a plus de caractres dans sa bote : la fonction recv Vous tes vir ! Sortez immdiatement de ce sous-marin !

Você também pode gostar