1 Le programme de l’atelier
Il s’agit d’un atelier de programmation réseau.
1.1 Programmation système
-
Analyse de paquets réseaux reçu par un micro-contrôleur.
- Implantation de la partie réseau d’un système d’exploitation.
- Dit autrement, implantation d’un embryon de pile TCP/IP.
- Paquets reçus sur une liaison série par le protocole SLIP :
-
simplification : pas de protocole Ethernet ;
- travail : implanter le procotole SLIP ;
- travail : analyser les entêtes IPv4 ;
- travail : analyser les datagrammes UDP ;
- utilisation des données UDP ;
- travail : générer des paquets IP/UDP.
- Plateforme Cortex M4 avec micro-python 1.10 installé.
1.2 Programmation applicative
-
Ecriture d’un embryon de serveur Web.
- Implantation basique du protocole HTTP.
- Utilisation de la bibliothèque des sockets (mode connecté).
- Communication avec la plateforme Cortex M4 par UDP.
- Utilisation de la bibliothèque des sockets (mode non connecté).
- Programmation en Python 3.5 sur un PC classique.
1.3 Configuration système basique
-
Définition d’une interface réseau SLIP.
- Affectation d’adresses IPv4 à l’interface SLIP.
2 Langage Python : généralités
-
Langage ancien (1991, pour comparaison C date de 1972).
- Langage généralement interprété (.py) mais ...
- ... possibilité de pré-analyse (.pyc).
- Langage typé mais sans typage statique.
- Une syntaxe pauvre et à indentation obligatoire.
- Moult paradigmes : impératif, objet, fonctionnel, ...
- Allocation automatisée (ramasse-miettes).
- Nombreuses bibliothèques (paquetages).
- Nombreuses versions (2.7, 3.5, micropython, etc).
3 Langage Python : bibliothèques
-
Une gestion des bibliothèques anarchique.
- Des bibliothèques empaquetées par le SE (e.g. python3-websockets).
- Un "preferred installer program" d’acronyme pip (ou pip3).
- Des bibliothèques gérées par pip (e.g. websockets).
- D’autres gestionnaires de bibliothèques comme conda d’anaconda.
- Passons sur les gestionnaires d’environnements virtuels.
4 Langage Python : constructions
-
Utilisation de bibliothèques :
import sys
sys.stderr.write('erreur')
- Définition de fonctions :
def inverse(chaine):
return '' if chaine=='' else chaine[-1:]+inverse(chaine[:-1])
- Alternative :
if x>y and x>z: x
elif y>x and y>z: y
else: z
- Boucle :
while True:
y=int(input())
if y>x: print('trop')
elif y<x: print('pas assez')
else:
print('exact')
break
- Énumération :
for i in range(1,4): print(i)
- Gestion d’exceptions :
try:
open("fichier","r")
except FileNotFoundError:
print("fichier non présent")
5 Langage Python : en vrac
-
Des chaînes de caractères :
-
initialisation ch=’’ ou ch=’ligne
\
n’ ;
- concaténation ch1+ch2 ;
- accès ch[0] ou ch[2:4] ou ch[2:] ;
- taille len(ch).
- Des listes :
-
initialisation l=[] ;
- concaténation l1+l2 ;
- ajout l.append(’a’) ;
- accès l[0] ou l[2:4] ou l[2:] ;
- taille len(l).
- Des outils pour la conversion de types :
-
chaîne vers entiers int("aa",16) ;
- entiers vers chaîne str(42) ;
- entiers vers chaîne ":02x".format(42).
- Des méthodes utiles :
-
lecture d’une ligne complète fichier.readline() ;
- épurage de ligne de caractères ligne.strip() ;
- découpage de ligne de caractères ligne.split(’;’) ;
- conversion en majuscules ligne.upper()
6 Langage Python : impératif
import sys
def somme(paquet):
somme=0
if(len(paquet)%2!=0): paquet.append(0)
for i in range(0,int(len(paquet)/2)):
mot=paquet[2*i]<<8 | paquet[2*i+1]
somme += mot
while somme>>16:
somme=(somme>>16)+somme&0xffff
return (~somme)&0xffff
paquet=[]
while True:
try:
for mot in input().split():
paquet.append(int(mot,16))
except EOFError:
break
print('somme='+format(somme(paquet),'04x'))
7 Langage Python : objet
-
Un vernis objet avec le mot clef class.
- Variables et méthode privées avec le préfixe __.
- Pas de polymorphisme, utiliser des méthodes de classe.
- Héritage multiple.
class paquetIPv4:
version=4
tailleEntete=5
tailleTotale=20
duree=64
protocole=0
somme=0
source=[]
cible=[]
donnees=[]
def __init__(self,source,cible,protocole,donnees):
self.source=source
self.cible=cible
self.protocole=protocole
self.donnees=donnees
self.tailleTotale=self.tailleEntete*4+len(donnees)
self.somme=somme(self.entetes())
@classmethod
def brut(classe,brut):
protocole=brut[9]
source=brut[12:16]
cible=brut[16:20]
donnees=brut[20:]
paquet=classe(source,cible,protocole,donnees)
paquet.version=brut[0]>>4
paquet.tailleEntete=brut[0]&0x0f
paquet.tailleTotale=brut[2]<<8|brut[3]
paquet.duree=brut[8]
paquet.somme=brut[10]<<8|brut[11]
return paquet
def adresses(self):
return self.source,self.cible
def liste(self):
return [ (self.version<<4)|self.tailleEntete, 0x00, *self.tailleTotale.to_bytes(2,byteorder='big'),
0x00, 0x00, 0x00, 0x00,
self.duree, self.protocole, *self.somme.to_bytes(2,byteorder='big'),
*self.source, *self.cible] + self.donnees
def entetes(self):
return self.liste()[0:self.tailleEntete*4]
def taille(self):
return self.tailleTotale
def valide(self):
return somme(self.entetes())==0
class paquetUDP(paquetIPv4):
portSource=0
portCible=0
sommeUDP=0
donneesUDP=[]
def __init__(self,IPSource,IPCible,portSource,portCible,donnees):
self.portSource=portSource
self.portCible=portCible
self.donneesUDP=donnees
paquetUDP=self.listeUDP()
pseudo_entetes=IPSource+IPCible+[*(len(self.donneesUDP)+8).to_bytes(2,byteorder='big')]+[0x00,0x11]
self.sommeUDP=somme(pseudo_entetes+paquetUDP);
bytes=self.sommeUDP.to_bytes(2,byteorder='big')
paquetUDP[6],paquetUDP[7]=bytes[0],bytes[1]
paquet=super().__init__(IPSource,IPCible,0x11,paquetUDP)
@classmethod
def brut(classe,brut):
paquet=paquetIPv4.brut(brut)
paquetUDP=paquet.donnees;
paquet.portSource=paquetUDP[0]<<8|paquetUDP[1]
paquet.portCible=paquetUDP[2]<<8|paquetUDP[3]
paquet.sommeUDP=paquetUDP[4]<<8|paquetUDP[5]
paquet.donneesUDP=paquetUDP[8:]
return paquet
def ports(self):
return self.portSource,self.portCible
def __pseudo_entetes(self):
return self.source+self.cible+[*(len(self.donneesUDP)+8).to_bytes(2,byteorder='big')]+[0x00,0x11]
def listeUDP(self):
entetesUDP=[ *self.portSource.to_bytes(2,byteorder='big'), *self.portCible.to_bytes(2,byteorder='big'),
*(len(self.donneesUDP)+8).to_bytes(2,byteorder='big'), *self.sommeUDP.to_bytes(2,byteorder='big') ]
return entetesUDP+self.donneesUDP
def tailleUDP(self):
return len(self.donneesUDP)
def valide(self):
IPvalide=super().valide()
UDPvalide=(somme(self.__pseudo_entetes()+self.listeUDP())==0)
return (IPvalide and UDPvalide)
>>> p1=paquetIPv4([192,168,0,1],[192,168,0,10],0x01,[0x08,0x00,0xf7,0xff])
>>> p1.liste()
[69, 0, 0, 24, 0, 0, 0, 0, 64, 1, 249, 137, 192, 168, 0, 1, 192, 168, 0, 10, 8, 0, 247, 255]
>>> p2=paquetIPv4.brut(p1.liste())
>>> p2.liste()==p1.liste()
True
>>> p2.adresses()
([192, 168, 0, 1], [192, 168, 0, 10])
>>> p3=paquetUDP([192,168,0,1],[192,168,0,10],1024,2048,[1,2,3,4])
>>> p3.adresses()
([192, 168, 0, 1], [192, 168, 0, 10])
>>> p3.ports()
(1024, 2048)
>>> p3.protocole
17
>>> p3.liste()
[69, 0, 0, 32, 0, 0, 0, 0, 64, 17, 249, 113, 192, 168, 0, 1, 192, 168, 0, 10, 4, 0, 8, 0, 0, 12, 110, 116, 1, 2, 3, 4]
>>> p3.valide()
True
>>> p4=paquetUDP.brut([69, 0, 0, 32, 0, 0, 0, 0, 64, 17, 248, 113, 192, 168, 0, 1, 192, 168, 0, 10, 4, 0, 8, 0, 0, 12, 110, 116, 1, 2, 3, 4])
>>> p4.valide()
False
8 Langage Python : fonctionnel
-
Utilisation des fonctions map, reduce et chain.
- Introduction des fonctions anonymes.
- Abomination : l’opérateur *.
import sys
import itertools
import functools
def lire():
paquet=list(map(lambda e: int(e,16),itertools.chain(*map(lambda ligne: ligne.split(),sys.stdin))))
if len(paquet)%2==1: paquet.append(0)
return paquet
def somme(paquet):
somme=functools.reduce(lambda x,y: x+y,map(lambda c: (c[0]<<8|c[1]),map(lambda i: (paquet[i],paquet[i+1]),range(0,len(paquet),2))))
while somme>>16: somme=(somme>>16)+somme&0xffff
return (~somme)&0xffff
print('somme='+format(somme(lire()),'04x'))
9 Langage Python : élégance et clareté
-
Abus des énumérables (un fichier est énumérable par ligne).
- Abus des fonctions anonyme (fonction anonyme et récursive).
import sys
import itertools
import functools
def lire():
return list(int(mot,16) for ligne in sys.stdin for mot in ligne.split())
def somme(paquet):
return(
~((lambda replier,somme: replier(replier,somme))(
lambda replier,somme:somme if not(somme>>16) else replier(replier,(somme>>16)+(somme&0xffff)),
functools.reduce(
lambda x,y: x+y,
[paquet[i]<<8|(0 if i>=len(paquet) else paquet[i+1]) for i in range(0,len(paquet),2)])))&0xffff
print('somme='+format(somme(lire()),'04x'))
10 Définition d’Internet
-
Interconnexion de réseaux locaux.
- Les données transitent sous forme de paquets.
- Les interconnexions utilisent TCP/IP.
- Présence de serveurs d’intérêt général.
- Modèle de réseaux en 7 couches.
11 Couche 1 : media physiques
-
De nombreux média de diffusion : radio, cuivre, fibres, ...
- Communication filaire robuste et efficace :
-
des connexions point à point bi-directionnelles ;
- pas de collision, possibilité de congestion ;
- des distances de plusieurs dizaines de kilomètre ;
- des débits jusqu’à 100 Gb/s.
- Communication radio fragile et capricieuse :
-
plusieurs flux spatiaux nécessitent plusieurs antennes ;
- très peu de canaux en 2,4Ghz (14 au plus et recouvrants) ;
- regroupement de canaux en 5Ghz pour un débit élevé ;
- des interférences passives (murs, portes, passants, ...) ;
- des interférences actives (autres points d’accès, ...) ;
- un medium partagé avec les autres utilisateurs ;
- affaiblissement avec la distance ;
- ...
12 Couche 2 : les réseaux locaux
-
Des caractéristiques communes :
-
réseau de petite taille (un bâtiment) ;
- possède un mécanisme de diffusion générale.
- Une technologie prédominante : Ethernet.
-
Format du paquet Ethernet :
6 octets | 6 octets | 2 octets | 48 à 1500 octets |
Adresse destination | Adresse source | Type | Données |
- Quelques types habituels :
-
0x0806 : paquet ARP ;
- 0x0800 : paquet IPv4 ;
- 0x86dd : paquet IPv6.
- Le format des adresses Ethernet :
-
les adresses Ethernet sont sur 6 octets ;
- identification unique d’une machine sur un réseau local ;
- des adresses point à point (unicast) et de diffusion (multicast) ;
- le préfixe de 3 octets est l’adresse constructeur ;
- exemple d’adresses Ethernet :
00:1a:a0:c0:17:6a |
ff:ff:ff:ff:ff:ff
|
- Une technologie plus récente : WiFi.
-
Le format des trames WiFi est complexe :
-
4 champs adresses ;
- un champ type de trame ;
- un champ durée de transmission ;
- un champ numéro de séquence ;
- ...
- Même format d’adresse qu’Ethernet.
13 Couche 2 : les réseaux locaux
-
Matériels : commutateurs Ethernet et points d’accès WiFi.
- Fonctionnement des commutateurs Ethernet :
-
équipement actif (alimenté électriquement) ;
- les commutateurs Ethernet gérent des paquets Ethernet ;
- un commutateur comprend de nombreux ports de connexion ;
- des commutateurs sont connectés entre eux par leurs ports ;
- les ordinateurs sont connectés aux ports via des interfaces Ethernet ;
- le nuage de commutation sait transmettre un paquet Ethernet ;
- les paquets sont transmis efficacement (diffusion évitée).
- Points d’accès WiFi :
-
équipement actif (alimenté électriquement) ;
- généralement une interface Ethernet ;
- généralement deux interfaces radio (2,4Ghz et 5Ghz) ;
- conversion entre le protocole WiFi et le protocole Ethernet ;
- définition de noms de réseau (SSID) ;
- dispositifs d’identification et de chiffrage (e.g. WPA2-PSK).
14 Couche 2 : le protocole ARP
-
Principe : trouver l’adresse Ethernet en fonction de l’adresse IPv4 ;
- Acronyme : Address Resolution Protocol ;
- Un paquet ARP est encapsulé dans un paquet Ethernet ;
- ARP se base sur la diffusion généralisée d’Ethernet ;
- ARP est efficace grâce à un cache des réponses ARP ;
- Le format du paquet ARP :
2 octets | 2 octets | 1 octet | 1 octet | 2 octets | 6 octets | 4 octets | 6 octets | 4 octets |
Type de matériel | Type de protocole | Longueur @ matérielle | Longueur @ protocole | Opération | @ émetteur matérielle | @ émetteur protocole | @ destinataire matérielle | @ destinataire protocole |
0x0001 | 0x0800 | 6 | 4 | 0x0001 ou 0x0002 | - | - | - | - |
- En IPv6 ARP est intégré dans le protocole ICMPv6.
15 Couche 3 : interconnexion de réseaux
-
Pile TCP/IP :
-
ensemble de protocoles réseau (IP, ICMP, UDP, TCP) ;
- définit le format des paquets d’échange de données ;
- définit comment un paquet est transmis sur un réseau local ;
- définit comment un paquet est routé entre les réseaux ;
- définit comment adresser un paquet à un processus.
- Fonctionnement des routeurs IP :
-
les routeurs n’utilisent pas de diffusion générale ;
- un routeur comprend des interfaces réseau (ports) ;
- des routeurs peuvent être interconnectés par leurs ports ;
- un commutateur Ethernet peut être connecté à un port ;
- le routeur examine, en particulier, l’adresse IP cible ;
- le routeur choisit le port de sortie via une table de routage ;
- une entrée de la table de routage concerne un réseau IP entier ;
- les entrées peuvent être saisie par un administrateur ;
- les entrées peuvent être apprises des autres routeurs.
16 Couche 3 : le protocole IP
-
Principe : Format d’échange de données entre deux ordinateurs d’Internet.
- Acronyme : Internet Protocol.
- La version actuelle est IPv4, la nouvelle est IPv6.
- Un paquet contient une entête et des données.
- L’entête contient les adresses IP de la source et de la cible :
4 bits | 4 bits | 1 octet | 2 octets | 4 octets | 1 octet | 1 octet | 2 octets | 4 octets | 4 octets |
Version | Longueur entêtes | Services et congestion | Longueur totale | Fragmentation | Durée vie | Protocole | Somme de contrôle | @ IPv4 source | @ IPv4 destination |
0x4 | 0x5 | 0x00 | - | 0x00000000 | 0x40 | - | - | - | - |
- Des protocoles encapsulés : 0x01 ICMP, 0x06 TCP ou 0x11 UDP.
- Dans un réseau local la résolution d’adresse se fait par ARP (IPv4) ou ICMP (IPv6).
- Format des adresses IP :
-
identification unique d’une machine sur Internet ;
- les adresses IPv4 sont sur 4 octets ;
- les adresses IPv6 sont sur 16 octets ;
- les réseaux IP sont des plages d’adresses contigües ;
- exemple d’adresses IPv4 :
- exemple d’adresses IPv6 :
fe80::1 |
2001:660:4401:6002:215:c5ff:fef3:e3f
|
- exemple de réseaux IPv4 :
192.168.0.0/255.255.255.0 |
193.48.57.0/26
|
- Calcul de la somme de contrôle :
-
porte sur l’entête IPv4 seule ;
- somme des mots de 16 bits avec repli des retenues ;
- programme C :
#include <stdio.h>
#include <stdint.h>
int main(void){
uint32_t sum=0;
uint8_t h,l;
while(scanf("%hhx",&h)==1){
if(scanf("%hhx",&l)!=1) l=0;
sum += ((uint16_t)h<<8)|l;
}
while(sum>>16) sum=(sum&0xffff)+(sum>>16);
printf("%04x\n",(uint16_t)~sum);
return 0;
}
17 Couche 3,5 : le protocole ICMPv4
-
Principe : véhicule les erreurs et les informations.
- Acronyme : Internet Control Message Protocol.
- Protocole de service de TCP/IP.
- Un paquet ICMPv4 est encapsulé dans un paquet IPv4.
- Permet de remonter les erreurs rencontrées (traceroute).
- Permet d’échanger des informations sur l’état du réseau (ping).
- Format des entêtes ICMPv4 :
- Principaux types et codes ICMPv4 :
Type | Code | Description |
0 | 0 | Réponse d’écho |
3 | 0 | Réseau inaccessible |
3 | 1 | Machine inaccessible |
3 | 2 | Protocole inaccessible |
3 | 3 | Port inaccessible |
3 | 4 | Fragmentation impossible |
4 | 0 | Limitation du débit de la source |
5 | 0 | Modification de route |
8 | 0 | Demande d’écho |
11 | 0 | Datagramme trop vieux |
18 Couche 4 : le protocole UDP
-
Principe : permet d’échanger des données entre processus.
- Acronyme : User Datagram Protocol.
- Protocole de transport de TCP/IP.
- Les paquets UDP sont encapsulés dans des paquets IP.
- Les données UDP sont les données des processus.
- Les processus sont adressés par la notion de ports.
- Des services utilisent des ports bien connus (53 pour le DNS).
- UDP est un protocole léger mais peu fiable :
-
perte de paquets possible ;
- duplication de paquets possible ;
- ordre de remise non garanti.
- Format des entêtes UDP :
2 octet | 2 octet | 2 octets | 2 octets |
Port source | Port destination | Longueur totale | Somme de contrôle |
- Somme de contrôle UDP :
-
même algorithme que pour IPv4 ;
- appliquer sur l’ensemble du paquet UDP ;
- prendre en compte une pseudo-entête :
-
adresses IPv4 ;
- code du protocole UDP sur 16 bits : 0x0011 ;
- taille du paquet UDP sur 16 bits.
19 Couche 4 : le protocole TCP
-
Principe : permet d’échanger des données entre processus.
- Acronyme : Transmission Control Protocol.
- Protocole de transport de TCP/IP.
- Les paquets TCP sont encapsulés dans des paquets IP.
- Les données TCP sont les données des processus.
- Les processus sont adressés par la notion de ports.
- Des services utilisent des ports bien connus (80 pour le Web).
- TCP est un protocole fiable :
-
établissement et terminaison de connexion ;
- envoi d’accusés de réception ;
- minuteurs pour ré-émission si nécessaire ;
- pas de perte de données, pas de doublon, remise dans l’ordre.
- Des entêtes complexes avec de nombreuses options.
- Même algorithme de calcul de la somme de contrôle qu’UDP.
20 Couche 5 : inexistante
-
Le modèle Open Systems Interconnection (OSI) de l’ISO est obsolète.
- Une légende urbaine dit que les rédacteurs étaient ivres :
Numéro de couche | Nom du nain | Nom de la couche | Explication |
1 | Dormeur | Physique | Les connexions physiques sont ennuyeuses |
2 | Atchoum | Lien | Un renifleur réseau montre une explosion de paquets |
3 | Joyeux | Réseau | Tout le monde est content de la couche réseau |
4 | Prof | Transport | Compliqué à comprendre (TCP en particulier) |
5 | Simplet | Session | Faudrait l’être pour en réaliser une |
6 | Timide | Présentation | Personne n’en a vu |
7 | Grincheux | Applications | Un développeur réseau est d’abord rude |
21 Couche 6 : inexistante
-
Le modéle Internet diffère du modèle OSI.
- Modèle Internet à 4 couches :
-
accès réseau ;
- Internet ;
- transport ;
- application.
22 Couche 7 : programmation réseau
-
Programmation en Python avec la bibliothèque des "sockets".
- Disponible depuis 1982 sous Unix BSD.
- Utilisée par la plupart des applications réseau.
- Caractéristiques des sockets :
-
deux sockets pour une communication ;
- représentation gros-boutiste des données ;
- plusieurs familles de sockets ;
- plusieurs modes pour une famille ;
- un adressage pour chaque famille.
- Familles de sockets actuelles :
-
PF_LOCAL : communication intra-système ;
- PF_INET : communication TCP/IPv4 ;
- PF_INET6 : communication TCP/IPv6 ;
- PF_BLUETOOTH : communication bluetooth.
- Modes principaux :
-
SOCK_STREAM : mode connecté ;
- SOCK_DGRAM : mode non connecté ;
- SOCK_RAW : mode accès direct.
- Structure d’adresses :
-
structure classique pour les prototypes struct sockaddr ;
- structure maximale pour le stockage struct sockaddr_storage ;
- type et nom de fichier pour AF_LOCAL ;
- type, adresse IPv4 et port pour AF_INET ;
- type, adresse IPv6, port, etc pour AF_INET6 ;
- type, adresse, canal pour AF_BLUETOOTH.
23 Couche 7 : sockets mode connecté
24 Couche 7 : sockets mode connecté
-
Une fonction d’initialisation de serveur :
import socket
import sys
def initialisationServeur(service,connexions):
infos=socket.getaddrinfo(
None,service,socket.AF_UNSPEC,socket.SOCK_STREAM,0,socket.AI_PASSIVE)
res=infos[0];
for info in infos:
if(info[0]==socket.AF_INET6): res=info
s=None
(famille,mode,protocole,nom,asocket)=res
try: s=socket.socket(famille,mode,protocole)
except socket.error as msg:
print('socket->'+str(msg),file=sys.stderr)
sys.exit(1)
try: s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
except socket.error as msg:
print('setsockopt(SO_REUSEADDR)->'+str(msg),file=sys.stderr)
sys.exit(1)
try: s.setsockopt(socket.IPPROTO_TCP,socket.TCP_NODELAY,1)
except socket.error as msg:
print('setsockopt(TCP_NODELAY)->'+str(msg),file=sys.stderr)
sys.exit(1)
try: s.bind(asocket)
except socket.error as msg:
print('bind->'+str(msg),file=sys.stderr)
s.close()
return None
try: s.listen(connexions)
except socket.error as msg:
print('listen->'+msg,file=sys.stderr)
sys.exit(1)
return s
- Une fonction d’attente des clients :
def boucleServeur(ecoute,traitement):
while(True):
(dialogue,asocket)=ecoute.accept()
if not traitement(dialogue):
ecoute.shutdown(socket.SHUT_RDWR)
return
- La fonction de traitement des clients :
def echo(dialogue):
f=dialogue.makefile("rw");
while(True):
line=f.readline()
if(len(line)==0): break
f.write('> '+line)
f.flush()
f.close()
try: dialogue.shutdown(socket.SHUT_RDWR)
except: pass
return True
- La fonction principale :
ecoute=stream_common.initialisationServeur("8000",1)
if ecoute!=None: stream_common.boucleServeur(ecoute,echo)
25 Couche 7 : sockets mode connecté
-
Un exemple de client :
def connexionServeur(hote,service):
infos=socket.getaddrinfo(hote,service,socket.AF_UNSPEC,socket.SOCK_STREAM)
res=infos[0];
for info in infos:
if(info[0]==socket.AF_INET6): res=info
s=None
(famille,mode,protocole,nom,asocket)=res
try: s=socket.socket(famille,mode,protocole)
except socket.error as msg:
print('socket->'+str(msg),file=sys.stderr)
sys.exit(1)
try: s.setsockopt(socket.IPPROTO_TCP,socket.TCP_NODELAY,1)
except socket.error as msg:
print('setsockopt(TCP_NODELAY)->'+str(msg),file=sys.stderr)
sys.exit(1)
try: s.connect(asocket)
except socket.error as msg:
print('connect->'+str(msg),file=sys.stderr)
s.close()
return None
return s
- La fonction principale :
import select
if len(sys.argv)!=3:
print("Syntaxe : exec <serveur> <service>\n",file=sys.stderr)
sys.exit(1)
hote=sys.argv[1]
service=sys.argv[2]
s=stream_common.connexionServeur(hote,service)
if s!=None:
oracle=select.poll()
oracle.register(s,select.POLLIN|select.POLLHUP|select.POLLERR)
oracle.register(0,select.POLLIN|select.POLLHUP|select.POLLERR)
while True:
resultats=oracle.poll()
for descripteur,drapeau in resultats:
if descripteur==s.fileno(): sys.stdout.write(s.recv(1).decode())
if descripteur==0: s.send(sys.stdin.readline().encode())
26 Couche 7 : sockets mode non connecté
27 Couche 7 : sockets mode non connecté
-
Un exemple de serveur :
import socket
import sys
def initialisationServeurUDP(service):
infos=socket.getaddrinfo(
None,service,socket.AF_UNSPEC,socket.SOCK_DGRAM,0,socket.AI_PASSIVE)
res=infos[0];
for info in infos:
if(info[0]==socket.AF_INET6): res=info
s=None
(famille,mode,protocole,nom,asocket)=res
try: s=socket.socket(famille,mode,protocole)
except socket.error as msg:
print('socket->'+str(msg),file=sys.stderr)
sys.exit(1)
try: s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
except socket.error as msg:
print('setsockopt(SO_REUSEADDR)->'+str(msg),file=sys.stderr)
sys.exit(1)
try: s.bind(asocket)
except socket.error as msg:
print('bind->'+str(msg),file=sys.stderr)
s.close()
return None
return s
- Boucle de réception des messages UDP :
def boucleServeurUDP(ecoute,traitement):
espace=bytearray(64*1024)
while(True):
taille,asocket=ecoute.recvfrom_into(espace)
donnees=bytearray(taille)
donnees=espace[0:taille]
if not traitement(donnees,asocket):
ecoute.shutdown(socket.SHUT_RDWR)
return
- Programme principal :
import os
def afficher(donnees,asocket):
print(asocket)
print(donnees)
return True
ecoute=dgram_common.initialisationServeurUDP("4000")
if ecoute!=None: dgram_common.boucleServeurUDP(ecoute,afficher)
28 Couche 7 : sockets mode non connecté
-
Un exemple de client :
def connexionServeurUDP(hote,service):
infos=socket.getaddrinfo(hote,service,socket.AF_UNSPEC,socket.SOCK_DGRAM)
res=infos[0];
for info in infos:
if(info[0]==socket.AF_INET6): res=info
s=None
(famille,mode,protocole,nom,asocket)=res
try: s=socket.socket(famille,mode,protocole)
except socket.error as msg:
print('socket->'+str(msg),file=sys.stderr)
sys.exit(1)
return s,asocket
- Programme principal :
import sys
import time
if len(sys.argv)!=3:
print("Syntaxe : exec <serveur> <service>\n",file=sys.stderr)
sys.exit(1)
hote=sys.argv[1]
service=sys.argv[2]
s,ssocket=dgram_common.connexionServeurUDP(hote,service)
if s!=None:
while True:
s.sendto(b"test !",0,ssocket)
time.sleep(1)
29 Couche 7 : Protocole DNS
-
Traduction de noms Internet en adresses IP.
- Exemple : www.polytech-lille.fr donne 193.48.57.52.
- La résolution inverse est possible.
- Exemple : 52.57.48.193.in-addr.arpa donne calais.escaut.net.
- De nombreuses autres informations sont disponibles.
- Exemple : polytech-lille.fr pour le type NS donne beuvry.escaut.net.
- Base de données distribuée et hiérarchique.
- Une résolution récursive :
-
requête "type A pour www.polytech-lille.fr" au serveur DNS local ;
- requête identique du DNS local à un serveur DNS racine (stockés sur disque) ;
- retour du serveur racine avec, comme indices, les serveurs DNS de fr ;
- requête initiale du DNS local à un serveur DNS de fr ;
- retour du serveur de fr avec, comme indices, les serveurs DNS de polytech-lille.fr ;
- requête initiale du DNS local à un serveur DNS de polytech-lille.fr ;
- réponse du serveur DNS de polytech-lille.fr "type A, adresse 193.48.57.52" ;
- mise en cache de la réponse et propagation au client DNS.
30 Couche 7 : Protocole HTTP
-
Sert des pages contenant des informations.
- Ces pages possédent des adresses appelées URL (Uniform Resource Locator).
- Les pages HTML (Hypertext Markup Language) contiennent des références à d’autres pages.
- Un protocole simple pour la toile : HTTP (Hypertext Transfer Protocol).
- Accès aux pages avec un client HTTP : un navigateur Web.
- Les navigateurs utilisent le DNS pour résoudre les URL.
- Les principales commandes HTTP :
-
GET : réclame un document ;
- HEAD : réclame uniquement les entêtes ;
- POST : envoi de données au serveur ;
- PUT : envoi du document d’URL spécifiée.
- Les différentes étapes de la récupération d’une page Web :
-
une requête du navigateur au serveur avec la commande GET ;
- envoi des entêtes annexes à la requête par le navigateur ...
- ... terminé par une ligne vide ;
- une réponse du serveur à la commande incluant un code numérique ;
- envoi des entêtes liées à la page par le serveur ...
- ... terminé par une ligne vide ;
- enfin transmission de la page par le serveur.
- Exemple de session HTTP :
$ nc www.polytech-lille.fr 80
GET / HTTP/1.1
Host: pevele.escaut.net
Accept: */*
User-Agent: WebParTelnet
From: Xavier.Redon@polytech-lille.fr
If-Modified-Since: Sat, 10 Jan 2003 19:43:31 GMT
HTTP/1.1 200 OK
Date: Tue, 11 Mar 2003 20:44:29 GMT
Server: Apache/1.3.27 (Unix) Debian GNU/Linux PHP/4.2.3
X-Powered-By: PHP/4.2.3
Transfer-Encoding: chunked
Content-Type: text/html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<HTML> <HEAD>
<TITLE>Polytech'Lille > Ecole polytechnique universitaire de Lille,
...
31 Couche 7 : Protocoles SMTP, POP et IMAP
-
Acronyme : Simple Mail Transfert Protocol.
- Acronyme : Post Office Protocol.
- Acronyme : Internet Message Access Protocol.
- Des clients de messagerie permettent d’envoyer des messages.
- Les messages sont envoyé à une ou des adresses de courriel.
- Les messages sont aiguillés grâce au DNS.
- Les messages sont reçus par des serveurs SMTP.
- Les serveurs SMTP confient les messages à des facteurs.
- Les facteurs stockent les messages dans des boites aux lettres.
- Un message est constitué d’une entête et d’un corps.
- Le corps d’un message est souvent au format MIME (Multipurpose Internet Mail Extensions).
- Des clients de messagerie récupérent les messages (POP ou IMAP).
- Exemple de session SMTP :
$ host -t MX polytech-lille.fr
polytech-lille.fr mail is handled by 50 peronne.escaut.net.
polytech-lille.fr mail is handled by 100 douaisis.escaut.net.
$ nc -C peronne.escaut.net 25
220 <serveur SMTP> ESMTP Sendmail ...
HELO <domaine du client SMTP>
250 <serveur SMTP> Hello pleased to meet you
MAIL FROM: <Zorro@monterey.org>
250 Zorro@monterey.org... Sender ok
RCPT TO: <Xavier.Redon@polytech-lille.fr>
250 Recipient ok
DATA
354 Enter mail, end with "." on a line by itself
Subject: Z comme zozo
Je tiens a vous dire que j'ai prevenu l'ISO de
votre manque de respect envers le modele OSI.
Zorro
.
250 PAA27560 Message accepted for delivery
QUIT
221 <serveur SMTP> closing connection
$
- Exemple de session POP :
$ nc pop.polytech-lille.fr 110
+OK <Serveur POP3> POP3 3.3(28) w/IMAP client
USER rex
+OK User name accepted, password please
PASS <shut!!>
+OK Mailbox rex open, 1 messages
LIST
+OK Mailbox scan listing follows
1 2234
.
TOP 1 1
+OK Top of message follows
Return-Path: <Zorro@monterey.org>
.
DELE 1
+OK Message deleted
QUIT
+OK Sayonara
$
- Exemple de session IMAP :
$ nc pop.polytech-lille.fr 143
* OK pevele Cyrus IMAP4 v1.5.14 server ready
tag1 login rex <shut!!>
tag1 OK User logged in
tag2 list "" *
* LIST () "." "INBOX"
* LIST () "." "INBOX.Drafts"
* LIST () "." "INBOX.Sent"
* LIST () "." "INBOX.Trash"
tag2 OK Completed
tag3 select inbox
* FLAGS (\Answered \Flagged \Draft \Deleted \Seen)
* 241 EXISTS
* 0 RECENT
* OK [UNSEEN 180]
tag3 OK [READ-WRITE] Completed
tag4 fetch 10 body[text]
* 10 FETCH (BODY[TEXT] {125}
Salut,
...
A+,
tag4 OK Completed
tag5 logout
* BYE LOGOUT received
tag5 OK Completed
$
Ce document a été traduit de LATEX par HEVEA