From 5b972850efc21f0a1b2d1ac349c7e74e18123416 Mon Sep 17 00:00:00 2001 From: Dimitri Merejkowsky Date: Sun, 1 Mar 2020 17:10:09 +0100 Subject: [PATCH] Ajout du chapitre 17 - sockets, http --- cours/source/17-sockets/1.png | Bin 0 -> 43190 bytes cours/source/17-sockets/exemple.rst | 128 ++++++++++++++++++++ cours/source/17-sockets/index.rst | 14 +++ cours/source/17-sockets/introduction.rst | 28 +++++ cours/source/17-sockets/protocoles.rst | 145 +++++++++++++++++++++++ cours/source/img/client-serveur.png | Bin 0 -> 4949 bytes cours/source/index.rst | 1 + 7 files changed, 316 insertions(+) create mode 100644 cours/source/17-sockets/1.png create mode 100644 cours/source/17-sockets/exemple.rst create mode 100644 cours/source/17-sockets/index.rst create mode 100644 cours/source/17-sockets/introduction.rst create mode 100644 cours/source/17-sockets/protocoles.rst create mode 100644 cours/source/img/client-serveur.png diff --git a/cours/source/17-sockets/1.png b/cours/source/17-sockets/1.png new file mode 100644 index 0000000000000000000000000000000000000000..000f48375c56864cae38f09bfbfbe1ba468c12a8 GIT binary patch literal 43190 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 P00000NkvXXu0mjf-ZKkl literal 0 HcmV?d00001 diff --git a/cours/source/17-sockets/exemple.rst b/cours/source/17-sockets/exemple.rst new file mode 100644 index 0000000..b6f6776 --- /dev/null +++ b/cours/source/17-sockets/exemple.rst @@ -0,0 +1,128 @@ +Exemple +======= + +Pour ce premier exemple, le client et le serveur vont tourner sur la même machine: la vôtre! + +Le processus du serveur tournera dans un premier terminal, et le processus du client dans un autre. + +Pour les différencier, on peut utiliser la variable `sys.ps1`. + +Étape 1 +------- + +Ouvrez deux terminaux, lancez dans chacun d'eux la commande `python3` sans arguments, puis tapez:: + + >>> import sys + >>> sys.ps1 = "(serveur) >>> " + +dans le premier, et:: + + >>> import sys + >>> sys.ps1 = "(client) >>> " + +dans le second. + +Vous devriez obtenir le résultat suivant:: + + (serveur) >>> + +:: + + (client) >>> + +Dans chacun d'eux, définissez les variables ``IP`` et ``PORT``:: + + (serveur) >>> IP = "127.0.0.1" + (serveur) >>> PORT = 3000 + +:: + + (client) >>> IP = "127.0.0.1" + (client) >>> PORT = 3000 + + +L'adresse IP ``127.0.0.1`` est spéciale et désigne votre propre machine. +Le PORT 3000 est un port arbitraire + + +Étape 2 +------- + +Dans le REPL du serveur, créez une socket du type 'AF_INET' et 'SOCK_STREAM', puis appelez +``bind()`` avec le tuple (IP, PORT) [#f1]_ :: + + + (serveur) >>> IP = "127.0.0.1" + (serveur) >>> PORT = 3000 + (serveur) >>> import socket + (serveur) >>> s_serveur = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + (serveur) >>> s_serveur.bind((IP, PORT)) + +Ensuite, appelez ``s_serveur.listen(0)``: cela permet à votre serveur d'accepter des connections:: + + (serveur) >>> s_serveur.listen(0) + +Enfin, appelez ``s_serveur.accept`: cette méthode retourne un tuple qu'on note souvent ``con, addr``:: + + (serveur) >>> con, addr = s_serveur.accept() + +Cette fois ci, vous devriez constater que le processus du serveur est *bloqué*: l'invite de commande ne s'affiche +pas - en effet, le serveur est en attente d'une connexion par le client + + +Étape 3 +------- + +De la même façon que pour le serveur, créez une socket du même type côté +client:: + + (client) >>> IP = "127.0.0.1" + (client) >>> PORT = 3000 + (client) >>> import socket + (client) >>> s_client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + +Ensuite, *connectez* la socket client à la socket serveur:: + + (client) >>> s_client.connect((IP, PORT)) + +Comme par magie, vous devriez voir le processus **dans l'autre terminal** reprendre son exécution: +les deux processus Python sont donc bien en train de *communiquer* + + +Étape 4 +------- + +Vous pouvez maintenant utiliser les méthodes ``send()`` et ``recv``, respectivement avec l'objet +``con`` côté serveur, et ``s_client`` côté client pour envoyer et recevoir des messages entre +les deux processus. + +Notez que ``send`` prend des ``bytes`` en arguments et renvoie le nombre d'octets envoyés, +et que ``recv()`` prend un nombre d'octets à lire. + +On peut envoyer des message du client vers le serveur:: + + + (client) >>> s_client.send(b"Bonjour") + 7 + +:: + + (serveur) >>> con.recv(7) + b'Bonjour' + + +Et du serveur vers le client:: + + (serveur) >>> con.send(b"Comment va ?") + 12 + +:: + + (client) >>> s_client.recv(12) + b'Comment va ?' + + +.. rubric:: notes + +.. [#f1] Il existe des sockets de plusieurs type et avec des comportements différents. AF_INET et SOCK_STREAM sont + les plus courants. diff --git a/cours/source/17-sockets/index.rst b/cours/source/17-sockets/index.rst new file mode 100644 index 0000000..067187c --- /dev/null +++ b/cours/source/17-sockets/index.rst @@ -0,0 +1,14 @@ +Chapitre 17 - Sockets +===================== + +Ce chapitre n'est pas à proprement parler un cours sur le langage +Python, mais contient des éléments qui nous servirons à bâtir +un projet à long terme : fabriquer un site Web ! + + +.. toctree:: + :maxdepth: 1 + + introduction + exemple + protocoles diff --git a/cours/source/17-sockets/introduction.rst b/cours/source/17-sockets/introduction.rst new file mode 100644 index 0000000..369c376 --- /dev/null +++ b/cours/source/17-sockets/introduction.rst @@ -0,0 +1,28 @@ +Introduction +============= + +Clients et serveurs +------------------- + +Dans le chapitre 15, nous avons parlé des données binaires et évoqué le +fait que cela permettait à nos programmes Python d'intéragir avec +l'extérieur, notamment via le système de fichiers. + +Il existe dans la librairie standard une autre façon pour Python de +communiquer via *le réseau* : il s'agit du module ``socket``. + +Une communication sur le réseau Internet implique: + +* Un *client* qui va faire des *requêtes* +* Un *serveur* qui va renvoyer des *réponses* au client +* Une *adresse* du serveur utilisée par le client + +Dans notre cas, cette adresse est un *tuple*, composé de deux éléments: +une *adresse IP* et un *port*. + +.. image:: /img/client-serveur.png + +En général: + +* Le *client* et le *serveur* sont sur des machines différentes +* Il n'y a qu'un seul processus qui est capable d'écouter sur un port donné diff --git a/cours/source/17-sockets/protocoles.rst b/cours/source/17-sockets/protocoles.rst new file mode 100644 index 0000000..156613d --- /dev/null +++ b/cours/source/17-sockets/protocoles.rst @@ -0,0 +1,145 @@ +Protocoles +========== + +Le problème +------------ + +Notez que ``send()`` et ``recv()`` sont très basiques: + +* On peut appeler ``send()`` plusieurs fois d'affilée +* On peut aussi appeler ``recv()`` alors que le client n'a encore rien envoyé, + le serveur va juste bloquer en attendant le prochain message du client. +* Si le client envoie 3 octets et que le serveur utilise ``recv(10)``, il n'y + a pas d'erreur +* Si le client envoie 10 octets et que le serveur utilise ``recv(3)``, il n'y + a pas non plus d'erreur, et il faut appeler ``recv()`` une deuxième fois + (avec 7 par exemple) pour récupérer le message en entier + + +Protocoles +----------- + +Ainsi, si on veut que deux machines s'échangent des messages via Internet, il faut +convenir d'un **protocole** - qui parle en premier, quel genre de message peut-il +envoyer? Il faut aussi convenir d'une façon de communiquer la *taille* des réponses. + + + +Le protocole HTTP +----------------- + +Le protocole HTTP est relativement simple. On peut le vérifier en essayant +de se connecter à l'adresse ``(93.184.216.34, 80)``, et envoyant les messages +suivants - à l'heure où j'écris ces lignes, l'IP ci-dessus correspond au site +``http://example.com`` :: + + import socket + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.connect(("93.184.216.34", 80)) + s.send(b"GET / HTTP/1.1\r\n") + s.send(b"Host: example.com\r\n") + s.send(b"\r\n") + + message = s.recv(351).decode() + print(message) + + +Résultat: + +.. code-block:: text + + HTTP/1.1 200 OK + Age: 514391 + Cache-Control: max-age=604800 + Content-Type: text/html; charset=UTF-8 + Date: Sun, 01 Mar 2020 15:57:23 GMT + Etag: "3147526947+ident" + Expires: Sun, 08 Mar 2020 15:57:23 GMT + Last-Modified: Thu, 17 Oct 2019 07:18:26 GMT + Server: ECS (bsa/EB18) + Vary: Accept-Encoding + X-Cache: HIT + Content-Length: 1256 + + + + +Notez qu'on a appelé `.decode()` sur le message reçu du serveur - on dit que HTTP +est un protocole de *texte*. + +Notez que la réponse du serveur rappelle le nom du protocole ``HTTP/1.1`` et répond avec +de nombreuses lignes contenant une *clé* et une *valeur* séparé par des deux-points + +On appelle cela des *en-têtes* (ou *headers*). L'un d'eux contient la taille totale du +message: ``Content-Length: 1256``. + +Après le bloc de headers, on voit le *corps* de la réponse: quelque chose qui commence +par ````. + +On peut lire la suite du message:: + + + suite = s.recv(1000).decode() + print(suite) + +.. code-block:: text + + + + Example Domain + + + + + + + + +

+

Example Domain

+

This domain is for use in illustrative examples in documents. You may use this + domain in literature without prior coordination or asking for permission.

+

More information...

+
+ + + + +Si maintenant vous allez sur ``https://example.com`` avec un navigateur Web, et cliquez sur +"Afficher le code source de la page", vous devriez voir exactement le contenu ci-dessus. + +Cela prouve que: + +* Il y a un serveur qui écoute sur l'adresse IP de example.com, sur le port 80 +* Ce serveur comprend le protocole HTTP +* Un navigateur ne fait rien d'autre que: + * envoyer des requêtes HTTP vers un serveur + * interpréter le texte retourné et l'afficher +* On peut facilement coder à la fois des *clients* et des *serveur* HTTP en Python, juste avec le module socket. + diff --git a/cours/source/img/client-serveur.png b/cours/source/img/client-serveur.png new file mode 100644 index 0000000000000000000000000000000000000000..aa4679278bbe5cdaa51ed36e1c1e77fa44134e2a GIT binary patch literal 4949 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 literal 0 HcmV?d00001 diff --git a/cours/source/index.rst b/cours/source/index.rst index fb4e6e7..7e3d0fb 100644 --- a/cours/source/index.rst +++ b/cours/source/index.rst @@ -33,3 +33,4 @@ remarques. 14-bibliothèques-01/index 15-fichiers-et-données-binaires/index 16-interpréteur-interactif/index + 17-sockets/index