Differences

This shows you the differences between two versions of the page.

Link to this comparison view

sde:laboratoare:10_fr_python [2020/04/22 10:15]
ioana_maria.culic [Exercice 4 - Serveur TCP]
— (current)
Line 1: Line 1:
-====== TP 10 - Communication en réseau ====== 
- 
-===== Présentation théorique ===== 
- 
-Pour pouvoir discuter de la communication dans un réseau, il est important de connaître les notions suivantes: 
-  *[[#Adresse physique|Adresse physique]] 
-  *[[#Adrese IP|Adresse IP]] 
-  *[[#​Port|Port]] 
- 
-===== Adresse physique ===== 
-L'​adresse physique, également appelée adresse MAC, est un nombre de 48 bits qui identifie de manière unique une carte réseau. Ce numéro est inscrit sur la carte réseau par le fabricant, donc généralement il ne peut pas être modifié. L'​adresse MAC est utilisée pour la transmission de données au niveau d'​accès au réseau dans la pile TCP / IP. 
- 
-Une adresse MAC est représentée en regroupant les 48 bits en 6 octets et en écrivant chaque octet dans la base 16 (ex: 00: A0: C9: 14: C8: 29 ou 00A0-C914-C829). 
- 
-===== Adresse IP ===== 
-Une adresse IP identifie une station dans un réseau et est utilisée pour la transmission de données au niveau du réseau à partir de la pile TCP / IP. 
- 
-Fondamentalement,​ l'IP d'une station est un nombre, 32 bits dans le cas du protocole IPv4 ou 128 bits dans le cas du protocole IPv6. Habituellement,​ les adresses IP sont écrites sous une forme restreinte. Dans le cas d'​IPv4,​ l'​adresse IP est écrite sous la forme de 4 chiffres dans la base décimale, avec des valeurs comprises entre 0 et 255, séparées par. (ex: 192.168.0.14),​ et dans le cas d'​IPv6,​ l'​adresse IP est écrite sous la forme de 8 groupes de nombres dans la base hexadécimale,​ avec des valeurs comprises entre 0000 et ffff, séparées par : (ex: 2001:​0db8:​85a3:​0000:​0000:​8a2e:​0370:​7334). ​ 
- 
-===== Port ===== 
-Le port est un identifiant utilisé pour la transmission de données au niveau de l'​application. 
- 
-Pour garantir que deux applications communiquent dans un réseau, nous devons spécifier l'​adresse IP des stations communicantes,​ ainsi que le port. Alors que l'​adresse IP garantit que les paquets arrivent à destination,​ le port garantit que le paquet reçu est utilisé par l'​application appropriée. 
- 
-Par exemple, deux ordinateurs peuvent communiquer à la fois pour échanger des e-mails, mais aussi pour réaliser une video-conférence. Ainsi, les deux ordinateurs échangent des messages pour les deux applications (messagerie électronique et video-conférence). Alors que les adresses IP sont utilisées pour garantir que tous les paquets arrivent au bon endroit, les applications de messagerie électronique et de video-conférence auront un port différent, en fonction des messages qui seront distribués à la bonne application. 
- 
-<note info> 
-Dans les applications développées par nous, nous devons nous assurer que nous choisissons une valeur pour le port qui n'est pas utilisée par d'​autres applications existantes sur le système. Sinon, nous risquons d'​avoir des conflits. C'est pourquoi nous choisissons les valeurs ** 8000 ** ou ** 8080 **, qui ne sont pas utilisées par les services connus. 
-</​note>​ 
-===== Socket ===== 
-Afin de pouvoir transmettre des messages sur le réseau, nous utiliserons des structures de socket. 
- 
-Un socket permet la transmission de messages entre applications sur la même machine ou sur différentes machines physiques, d'une manière similaire à celle utilisant des descripteurs de fichiers. 
- 
-En Python, on va utiliser le module [[https://​docs.python.org/​3/​library/​socket.html|socket]] pour les opérations de communication en réseau. Parmi les opérations que nous pouvons effectuer en utilisant le module "​socket"​ figurent: 
-  * [[#Obtenir des informations sur la station actuelle|Obtenir des informations sur la station actuelle]]; 
-  * [[#Obtenir des informations sur d'​autres éléments du réseau|Obtenir des informations sur d'​autres éléments du réseau]]; 
-  * [[#Créer des connexions TCP|Créer des connexions TCP]]; 
-  * [[#​Échanger des données en réseau|Échanger des données en réseau]]. 
- 
-==== Obtenir des informations sur la station actuelle ==== 
-La fonction [[https://​docs.python.org/​3/​library/​socket.html#​socket.gethostname|gethostname]] renvoie l'​adresse IPv4 de la station locale. 
-<code python> 
-socket.gethostname() 
-</​code>​ 
- 
-====Obtenir des informations sur d'​autres éléments du réseau==== 
-La fonction [[https://​docs.python.org/​3/​library/​socket.html#​socket.getaddrinfo|getaddrinfo]] renvoie une liste de 5 éléments qui contiennent des informations sur une adresse et un port spécifiés. La liste renvoyée contient les informations suivantes: ''​(family,​ type, proto, canonname, sockaddr)'',​ et ''​sockaddr''​ est une autre liste qui contient ''​(address,​ port)''​. 
-<code python> 
-socket.getaddrinfo(host,​ port, family=0, type=0, proto=0, flags=0) 
-</​code>​ 
- 
-La fonction[[https://​docs.python.org/​3/​library/​socket.html#​socket.gethostbyname|gethostbyname]] renvoie l'​adresse IPv4 d'un ''​hostname''​. 
-<code python> 
-socket.gethostbyname(hostname) 
-</​code>​ 
- 
-====Création de connexions TCP==== 
-En utilisant des sockets, nous pouvons réaliser deux types de transmission de données: UDP ou TCP. 
- 
-Pour les deux types de transmissions,​ nous devons créer un nouvel objet socket à l'aide de la fonction [[https://​docs.python.org/​3/​library/​socket.html#​socket.socket|socket (family=AF_INET,​ type=SOCK_STREAM,​ proto=0, fileno=None)]]. 
-Selon les paramètres transmis au constructeur,​ le socket est configuré pour un certain type de transfert de données. 
- 
-  * family - représente le type d'​adressage utilisé (ex: pour IPv4, le type utilisé est ''​ AF_INET '',​ pour IPv6 le type est ''​ AF_INET6 ''​);​ dans notre cas, nous utiliserons AF_INET (socket.AF_INET,​ en Python); 
-  * type - représente le type de transfert de données utilisé; en général, nous choisirons entre ''​ SOCK_STREAM ''​ (pour le transfert TCP) et ''​ SOCK_DGRAM ''​ (pour le transfert UDP); 
-  * proto - représente le protocole utilisé, dans notre cas nous laisserons la valeur par défaut; 
-  * fileno - représente un ''​ descripteur de fichier '',​ et si ce paramètre est passé, toutes les 3 autres valeurs sont définies automatiquement en fonction de celui-ci. 
- 
-<code python> 
-import socket 
-s = socket.socket() 
-</​code>​ 
- 
-Pour le transfert TCP,  on utilise le paradigme client-serveur,​ dans lequel un processus attend les connexions (serveur), tandis que d'​autres processus peuvent s'y connecter (client). En utilisant TCP, les données transmises atteindront sûrement la destination ou une erreur sera reçue. 
- 
-===Initialisation du serveur=== 
-Pour démarrer un serveur en mode socket, nous devons effectuer les opérations suivantes: 
-  * Attribuer une adresse et un port au socket ([[https://​docs.python.org/​3/​library/​socket.html#​socket.socket.bind|bind]]) 
-  * Préciser que nous attendons des connexions et combien ([[https://​docs.python.org/​3/​library/​socket.html#​socket.socket.listen|listen]]) 
-  * Accepter les connexions entrantes ([[https://​docs.python.org/​3/​library/​socket.html#​socket.socket.accept|accept]]);​ la fonction renvoie un tuple avec deux valeurs: la connexion et une adresse; la connexion est une variable socket qui sera utilisée pour transmettre des messages; l'​adresse est l'​adresse du programme qui s'est connecté. 
- 
-<note info> 
-Si l'​adresse IP transmise à la fonction ''​ bind ''​ est ''​ 0.0.0.0 '',​ le socket prend en charge les connexions sur toutes les cartes réseau. 
-</​note>​ 
-==Exemple== 
-<code python> 
-import socket 
-s = socket.socket() 
-s.bind(('​0.0.0.0',​ 8000)) 
-s.listen(0) 
-conn, addr = serv.accept() 
-</​code>​ 
- 
-===Initialisation du client=== 
-Pour établir une connexion à partir du serveur, en utilisant le mode socket, nous devons appeler la fonction [[https://​docs.python.org/​3/​library/​socket.html#​socket.socket.connect|connect]]. 
- 
-Pour mettre fin à la connexion avec le serveur, nous utiliserons la fonction [[https://​docs.python.org/​3/​library/​socket.html#​socket.socket.close|close]]. 
-==Exemple== 
-<code python> 
-import socket 
-s = socket.socket() 
-s.connect(('​localhost',​ 8000)) 
-# send/​receive data 
-s.close() 
-</​code>​ 
- 
-<note info> 
-Pour se connecter à un service exécuté sur la machine locale, on peut utiliser l'​adresse ''​ localhost ''​ ou ''​ 127.0.0.1 ''​. 
-</​note>​ 
- 
-====Échange de données en réseau==== 
-===Envoi de données=== 
-Pour envoyer des données à l'aide du module socket, nous pouvons utiliser les fonctions [[https://​docs.python.org/​3/​library/​socket.html#​socket.socket.send|send]] et [[https://​docs.python.org/​3/​library/​socket.html#​socket.socket.sendto|sendto]]. 
-<code python> 
-socket.send(bytes[,​ flags]) 
-socket.sendto(bytes,​ address) 
-socket.sendto(bytes,​ flags, address) 
-</​code>​ 
- 
-La fonction ''​send''​ envoie des données uniquement si le socket est connecté à un autre socket, il ne peut donc être utilisé que pour une transmission TCP. 
- 
-La fonction ''​sendto''​ envoie des données à une adresse passée en paramètre, sans nécessiter de connexion entre les deux objets socket, afin qu'​elle puisse être utilisée pour la transmission UDP. 
-<note info> 
-Le paramètre "​address"​ est un tuple de type (adresse, port), par exemple:​("​0.0.0.0",​ 8000). 
-</​note> ​ 
- 
-===Réception de données=== 
-Pour recevoir des données en utilisant le module ''​socket''​ nous pouvons utiliser les fonctions [[https://​docs.python.org/​3/​library/​socket.html#​socket.socket.recv|recv]] et [[https://​docs.python.org/​3/​library/​socket.html#​socket.socket.recvfrom|recvfrom]]. 
-<code python> 
-socket.recv(bufsize[,​ flags]) 
-socket.recvfrom(bufsize[,​ flags]) 
-</​code>​ 
- 
-La fonction ''​ recv ''​ lit les données à leur taille maximale, spécifiée comme paramètre (''​ bufzise ''​),​ et les retourne comme un objet ''​bytes''​. Cette fonctionnalité convient à la transmission TCP, où nous avons une connexion constante à une autre socket. 
- 
-La fonction ''​recvfrom''​ lit des données similaires à la fonction ''​ recv '',​ mais renvoie deux objets: le message et l'​adresse source. Ainsi, nous pouvons utiliser l'​adresse retournée pour renvoyer des messages. Cette fonctionnalité convient à la transmission UDP, où nous n'​avons aucune connexion à une autre prise. 
-<note info> 
-L'​objet ''​address''​ renvoyé est un tuple de type (adresse, port), par exemple ("​0.0.0.0",​ 8000).</​note> ​ 
- 
-=====Exemples===== 
-Dans ces exemples, nous allons créer un processus qui attend et répond continuellement aux messages (serveur) et un autre processus qui envoie un message et attend une réponse (client). 
-<note info> 
-Afin de tester la communication sur le réseau à l'aide d'un seul ordinateur, nous allons créer deux fichiers sources simulant chacun le comportement d'une station réseau différente. Pour tester la communication,​ nous exécuterons les deux programmes en parallèle. 
-</​note>​ 
-====Exemple UDP==== 
-===Server=== 
-<code python> 
-import socket 
- 
-buffersize = 2048 
-# create socket 
-s = socket.socket(family=socket.AF_INET,​ type=socket.SOCK_DGRAM) 
-# bind socket to address and port 
-s.bind (("​0.0.0.0",​ 8000)) 
- 
-# listen for data forever and reply with "​Message received"​ 
-while True: 
-    data, addr = s.recvfrom(buffersize) 
-    print ("Data from {} is {}"​.format (addr, data)) 
-    msg = str.encode ("​Message received"​) 
-    s.sendto (msg, addr) 
-</​code>​ 
-===Client=== 
-<code python> 
-import socket 
-buffersize = 2048 
- 
-# create socket 
-s = socket.socket(family=socket.AF_INET,​ type=socket.SOCK_DGRAM) 
-# create bytes object 
-msg = str.encode("​Hello"​) 
-# send message 
-s.sendto (msg, ("​localhost",​ 8000)) 
-# read message 
-data, addr = s.recvfrom (buffersize) 
-print ("Data from {} is {}"​.format (addr, data)) 
-</​code>​ 
- 
-<note info> 
-Pour tester l'​exemple,​ exécutez d'​abord le serveur puis le client sur un autre terminal. 
-</​note>​ 
- 
-====Exemple TCP==== 
-===Server=== 
-<code python> 
-import socket 
- 
-buffersize = 2048 
-# create socket 
-s = socket.socket (family=socket.AF_INET,​ type=socket.SOCK_STREAM) 
-# bind socket to address and port 
-s.bind (("​0.0.0.0",​ 8000)) 
-# wait for connections 
-s.listen (0) 
-# accept connections forever 
-while True: 
-    conn, addr = s.accept () 
-    print ("​Connected to {}"​.format (addr)) 
- 
-    # listen for data and reply with "​Message received"​ 
-    while True: 
-        data = conn.recv(buffersize) 
-        # client finished sending message 
-        if not data: 
-            break 
-        print ("​Received {}"​.format (data)) 
-        msg = str.encode ("​Message received"​) 
-        conn.send (msg) 
-    # close connection 
-    conn.close () 
-</​code>​ 
- 
-===Client=== 
-<code python> 
-import socket 
-buffersize = 2048 
- 
-# create socket 
-s = socket.socket(family=socket.AF_INET,​ type=socket.SOCK_STREAM) 
-# connect to server 
-s.connect (("​localhost",​ 8000)) 
-# create bytes object 
-msg = str.encode("​Hello"​) 
-# send message 
-s.send (msg) 
-# read message 
-data, addr = s.recv (buffersize) 
-# close connection 
-s.close () 
- 
-print ("Data from {} is {}"​.format (addr, data)) 
-</​code>​ 
- 
- 
-====== Exercices de laboratoire ====== 
- 
-Pour résoudre le laboratoire,​ utilisez le référentiel github. Pour télécharger le référentiel,​ exécutez la commande git clone https://​github.com/​UPB-FILS/​sde.git dans le terminal. 
- 
-===== Exercice 1 - Informations sur le réseau ===== 
-  - Créer un programme qui affiche l'​adresse physique, l'​adresse IP et le nom de la station. 
-  - Afficher l'​adresse IP de google.com. 
- 
-===== Exercice 2 - Netcat ===== 
-Netcat est un utilitaire de la ligne de commande qui permet des opérations réseau. Dans cet exercice, nous allons l'​utiliser pour échanger des messages avec des programmes python dans les exemples ci-dessus. 
-  - Exécutez l'​application serveur à partir de l'​exemple de transmission TCP, puis dans un autre terminal, en parallèle, exécutez la commande: ''​ netcat -z -v localhost 8000 ''​. Notez la réponse reçue. 
-  - Exécutez l'​application serveur à partir de l'​exemple de transmission UDP, puis exécutez une autre commande en parallèle, exécutez la commande: ''​ echo test | netcat -u localhost 8000 ''​. Notez le comportement résultant (l'​option -u spécifie le mode de transmission UDP).  
-  - Envoyer un message au programme du serveur TCP en utilisant ''​netcat''​. 
-  - Exécutez la commande netcat -lu -p 8080, qui démarre un serveur UDP sur le port 8080. Modifiez l'​exemple de laboratoire pour envoyer un message au serveur démarré. 
-  - Exécutez la commande netcat -l -p 8080, qui démarre un serveur TCP sur le port 8080. Modifiez l'​exemple de laboratoire pour envoyer un message au serveur en cours d'​exécution. 
- 
-===== Exercice 3 - UDP ===== 
- 
-Créez deux programmes qui communiquent en mode UDP via socket afin que l'un des programmes reçoive trois nombres séparés par '';​ ''​ et réponde avec leur moyenne arithmétique. 
- 
- 
-===== Exercice 4 - Serveur TCP ===== 
-Simulez un serveur TCP qui reçoit des commandes bash et répond avec leur résultat. Créez un client qui envoie des commandes et affiche le résultat reçu du serveur. Astuce: utilisez un pipe pour stocker la sortie de la commande démarrée. 
-===== Exercice 5 - Serveur TCP multi-threaded ===== 
-Modifiez le serveur créé au point précédent pour prendre en charge plusieurs connexions simultanées. Utilisez des threads dans la mise en œuvre. 
-Astuce: Le programme principal accepte les connexions et une fois la connexion établie, démarrez un nouveau thread qui reçoit la connexion en tant que paramètre. 
-<​hidden>​ 
-===== Exercițiul 5 - client Web ===== 
-- sa ia date de pe internet 
-===== Exercițiul 7 - Simple HTTP Server ===== 
-- sa faca server cu simple http server 
-</​hidden>​ 
- 
  
sde/laboratoare/10_fr_python.1587539731.txt.gz · Last modified: 2020/04/22 10:15 by ioana_maria.culic
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0