Les sockets sont basés sur une architecture client/serveur: Le serveur décide d’accepter les demandes de connection sur un port particulier, tandis que le client demande une connexion sur le serveur.
Une fois la connexion établie, les deux programmes peuvent communiquer sur la socket ‘s’ à l’aide de lecture (en fait une réception ‘s.recv()') et d’écriture (en fait une émission : ‘s.send()').
#Un client http très simple import socket # un exemple d'interrogation d'un serveur DNS print("Interrogation du DNS: "+socket.gethostbyname("www.univ-tln.fr")) #1- Construire un objet qui représente la socket # vers laquelle le client veut se connecter s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #2- ouvrir la connection vers la socket s.connect(("www.univ-tln.fr",80)) #3- construire le message à envoyer (ici une requête http). request = "GET / HTTP/1.1\r\n" request+= "Host: www.univ-tln.fr\r\n" request+= "Connection: Close\r\n\r\n" #4- l'envoyer sur la socket s.send(request.encode('UTF-8')) #5- lire 15 octet sur la socket (augmenter pour lire plus...) data = s.recv(15) # convertir le tableau de 15 octets en une chaine de caractère # et l'afficher. print(data.decode('utf-8')) s.close()
lsis.univ-tln.fr
.
Attention, il y a plusieurs difficultés :
Ce module https://docs.python.org/3/library/struct.html#module-struct offre les fonctions de conversion.
Convert 32-bit positive integers from host to network byte order. On machines where the host byte order is the same as network byte order, this is a no-op; otherwise, it performs a 4-byte swap operation.
time.ctime()
pour afficher de façon lisible la date. cf. https://docs.python.org/3/library/time.html pour les conversion de temps en python.L’échange suivant montre un échange avec le protocole FTP (sur ftp.univ-tln.fr) pour se connecter et obtenir des informations sur le système.
220 mail1.univ-tln.fr FTP server (Version wu-2.6.2(1) Fri Feb 14 10:45:38 CET 2003) ready.
USER anonymous
331 Guest login ok, send your complete e-mail address as password.
PASS anonymous
230-Please read the file README
230- it was last modified on Fri Feb 14 11:16:03 2003 - 4248 days ago
230 Guest login ok, access restrictions apply.
SYST
215 UNIX Type: L8 Version: BSD-198911
L’idée est générale est d’utiliser un automate. Le programme lit sur la socket et en fonction de ce qu’il lit et de l’état dans lequel il se trouve et envoie le bon message : Lire les lignes à l’infini :
USER …
et je passe à l’état 1. Pour faciliter le traitement des chaînes sur les sockets ce qui arrive très souvent :
for line in s.makefile(‘r’):
# Définition d'un serveur simple # Le serveur attend la connexion d'un client et fait un echo des messages reçu import socket, sys #Adresse ip et port de la socket sur laquelle va ecouter le serveur # A ADAPTER A VOTRE MACHINE, vous pouvez mettre 0.0.0.0 pour écouter sur toutes les adresses IP du serveur # quelle est la conséquence d'écouter sur 127.0.0.1 ? HOST = '127.0.0.1' PORT = 2003 # 1) Il faut créer la socket en indiquant les protocoles (ici IP et TCP) mySocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 2) puis effectuer la liaison (bind) try: mySocket.bind((HOST, PORT)) except socket.error: print("La liaison du socket à l'adresse choisie a échoué.") sys.exit() # 3) Un serveur est souvent une boucle infinie qui attend des connexions. while 1: # 4) Le serveur se bloque en attente de la requête de connexion d'un client print("serveur simple en attente...") mySocket.listen(5) # 5) Il est débloqué lors de l'établissement de la connexion connexion, adresse = mySocket.accept() print("Un client est connecté depuis l'adresse IP %s et le port %s" % (adresse[0], adresse[1])) # 6) Envoi d'un message de bienvenue au client # Attentionn la chaine de caractère DOIT etre convertie en un tableau d'octets # le paramète 'UTF-8" indique l'encodage des caratère qui doit être utilisé. connexion.send(("Vous êtes connecté au serveur "+HOST+":"+str(PORT)+".\n").encode('UTF-8')) # Le serveur commence maintenant un echange avec le client connecté while 1: # envoi de la question au client connexion.send("Votre message ?\n".encode('UTF-8')) # attente de la reponse msgClient = connexion.recv(1024) # le message est converti d'une tableau d'octets en chaine de caractères msgClient = msgClient.decode("utf-8") #si la reponse est FIN ou un ligne vide, le dialogue d'arrête. if msgClient.upper().strip() == "FIN" or msgClient.strip() == "": break # traitement de la réponse # le serveur affiche sur sa console print("reçu du client>"+msgClient+"<") # et envoi un echo au client connexion.send(("ECHO : "+msgClient).encode('UTF-8')) # 7) Si l'on est sorti de la boucle il faut terminer connexion.send("Good Bye.".encode('UTF-8')) print("Connexion interrompue.") #Le serveur ferme la connexion connexion.close() ch = input("Attendre un autre client ? <R>ecommencer <T>erminer ? ") if ch.upper() =='T': break
./rsswatch.py http://www.univ-tln.fr/backend-breves.php3 informatique bruno@univ-tln.fr
envoi un email à bruno@univ-tln.fr quand le mot “informatique” est trouvé dans un titre d’une nouvelle de la page http://www.univ-tln.fr/backend-breves.php3
—- dataentry page —- type : TP enseignement_tags : S52 technologies_tags : Socket, TCP, Python themes_tags : Réseaux