Cours et exercices Programmation socket en ruby


Télécharger Cours et exercices Programmation socket en ruby
3.53.5 étoiles sur 5 a partir de 1 votes.
Votez ce document:

Télécharger aussi :


Cours et exercices Programmation socket en ruby

...

Sockets en Ruby : client TCP

1 Nous allons utiliser la bibliothèque ’socket’

2 TCPSocket.open renvoie un objet client qui est ensuite utilisé pour gérer la connexion

3 Si la connexion est bien établie, l’objet client permet de communiquer via des méthodes comme gets ou puts

4 La connexion doit être fermée

1 r e q u i r e ’ so c ket ’

2 c l i e n t = TCPSocket . open ( " 1 2 7. 0. 0. 1 " , 1234)

3 c l i e n t . put s ( " S a l ut " ) ; c l i e n t . put s ( "Au r e v o i r " )

4 c l i e n t . c lo se ( )

Sockets en Ruby : serveur TCP

La classe TCPServer permet de construire un serveur (via TCPServer.open)

Ce serveur doit “accepter” un client qui se connecte

Résultat : un objet session de connexion socket serveur ↔ socket client

L’objet résultant permet de recevoir des données (via gets) ou bien d’envoyer (puts)

1 # ! / u s r / b i n / ruby

2 r e q u i r e ’ so c ket ’

3 s e r v e r = TCPServer . open(1234 )

4 se s sion = s e r v e r . accept ( )

5 put s ( se s sion . get s ( ) )

6 se s sion . put s ’ Bien recu ’

7 se s sion . c lo se ( )

Sockets en Ruby : client UDP

Le client UDP est différent du client TCP. Voici quelques opérations

Création socket local via UDPSocket.new

“Connexion” à une socket UDP distant pas une vraie connexion comme pour TCP cette opération fait le nécessaire pour pouvoir envoyer/recevoir des données

Le port local est disponible via l’attribut addr

Envoi et réception de données via send()/recvfrom()

1 # ! / u s r / b i n / ruby

2 r e q u i r e ’ so c ket ’

3 maSocketUdp = UDPSocket . new

4 maSocketUdp . connect ( " 1 2 7. 0. 0. 1 " , 1234)

5 put s maSocketUdp . addr [ 1 ]

6 maSocketUdp . send ( " aaa " , 0 )

7 put s maSocketUdp . re c vf rom ( 1 0 0 , 0 )

8 maSocketUdp . c lo se

Sockets en Ruby : serveur UDP

On utilise toujours un objet UDPSocket : la méthode bind() associe la socket UDP à un port local

IP local : 0.0,0,0, port à votre choix

Réception de messages : recvfrom (pas de gets() comme pour TCP) → un tableau à deux positions : pos 0 Le message : une chaîne de caractères

pos 1 Informations sur l’émetteur : tableau à 4 positions :[0] type adresse, [1] port, [2] nom, [3] ip émetteur

1 r e q u i r e ’ so c ket ’

2 sockUdp = UDPSocket . open ( )



3 sockUdp . bind ( " 0 . 0 . 0 . 0 " , 1234)

4 f o r i i n 1 . . 5 do

5 msg = sockUDP. re c vf rom ( 1 0 0 , 0 )

6 put s "Recu msg de "+msg [ 1 ] [ 3 ] + " : "+msg [ 0 ]

7 end

8 sockUdp . c lo se ( )

16/48

Sockets en Ruby : UDP en diffusion

Pour pouvoir envoyer des paquets en diffusion, l’objet

UDPSocket doit activer l’option Socket::SO_BROADCAST

Méthode utilisée : setsockopt(niveau,option,valeur)

niveau=Socket::SOL_SOCKET – modifications au niveau de la socket (et non pas SOL_TCP, SOL_UDP) option=Socket::SO_BROADCAST et valeur=true

L’adresse de diffusion est disponible via ifconfig

1 r e q u i r e ’ so c ket ’

2 sockUdpBCast = UDPSocket . new

3 sockUdpBCast . set so c kopt ( Socket : :SOL_SOCKET, Socket : :SO_BROADCAST, t r u e )

4 sockUdpBCast . connect ( " 172.31.25.255 " , 1234)

5 sockUdpBCast . send ( " S a l ut l e monde" , 0 )

6 sockUdpBCast . c lo se ( )

Méthodes importantes (bibliothèque socket)

Socket.gethostname() : le nom de la machine locale

Socket.getservbyname(nomService) : renvoie le port associé au service nomService

Socket.getnameinfo(domain,port,ip) : renvoie des

informations sur la socket : ip:port

Exemple : Socket.getnameinfo(["AF_INET", ’23’, ’88.221.216.34’]) "AF_INET" indique le fait qu’il s’agit d’une adresse IPv4 (Internet)

Socket.getaddrinfo(nommachine, service) : renvoie des informations numériques (l’IP) par rapport au service

service et la machine nommachine.

Exemple : Socket.getaddrinfo(’…’, ’http’)

Résumé des sockets

Sockets TCP

client Exemple : session=TCPSocket.open(...)

serveur Deux opérations : open et accept

serv=TCPServer.open(...)

session=serv.accept()

utilisation session.puts(...) et session.gets(...)

Sockets UDP

client Création objet et connexion à distance (pas une vraie connexion comme pour

TCP)

sockUDP=UDPSocket.new

sockUDP.connect(...)

serveur Deux opérations : open et bind

sockUDP=UDPSocket.open()

sockUDP.bind(...)

utilisation sockUdp.send(...) ou sockUdp.recvfrom

Le flux du programme : paradigme classique

Paradigme séquentiel

Un programme = une séquence d’instructions en série :

1 a=b



2 c=a*a-a

3 puts(Math.log(c))

4 .....

1 toute erreur peut provoquer un crash du programme

2 pas possible de gérer plusieurs clients au même temps

3 l’interaction avec l’utilisateur est programmée en avance l’utilisateur intervient uniquement lorsqu’on arrive à une instruction

comme gets()

Le programme ci-dessus cache une erreur

La valeur de c peut être négative : a < 1 ⇒ a × a − a < 0

Le flux du programme : paradigme classique

Paradigme séquentiel

Un programme = une séquence d’instructions en série :

1 a=b

2 c=a*a-a

3 puts(Math.log(c))

4 .....

1 toute erreur peut provoquer un crash du programme

2 pas possible de gérer plusieurs clients au même temps

3 l’interaction avec l’utilisateur est programmée en avance l’utilisateur intervient uniquement lorsqu’on arrive à une instruction

comme gets()

Le programme ci-dessus cache une erreur

La valeur de c peut être négative : a < 1 ⇒ a × a − a < 0

Le flux du programme : nouveau paradigme

Paradigme non-séquentiel

La programmation graphique/réseau change par rapport à la programmation "classique" séquentielle

Exceptions définir la réaction aux conditions exceptionnelles rencontrées pendant l’exécution du programme

Événements définir la réaction différents événements (un clic de souris)

Fils d’exécutions (threads) permettre l’exécution de plusieurs routines au même temps (ex. plusieurs clients)

… … …

Exercice 1 : Transferts UDP

Le protocole UDP utilise des paquets appelés "datagrams" pour effectuer des communications de façon non-fiable en mode non-connecté. Cela signifie qu’il n’est pas possible de savoir si les datagrams envoyés ont bien été reçus et qu’il n’est pas possible de savoir si les datagrams reçus l’ont été dans le bon ordre.

Dans cet exercice nous allons écrire deux programmes qui s’échangent une chaîne de caractère en utilisant le pro-tocole UDP. Le programme source envoie une chaîne de caractère à l’adresse IPv4 et au numéro de port spécifiés sur la ligne de commande au lancement du programme. De même, le programme récepteur réceptionne la chaîne de caractère envoyée et l’affiche à l’écran. Le numéro de port utilisé par le récepteur doit être passé en paramètre au lancement du programme.

Exercices :

  • Programmez en ruby les programmes sources et récepteurs.
  • Lancez le récepteur puis l’expéditeur avec les bons paramètres et vérifiez que la chaîne envoyée par l’expéditeur est correctement affichée du côté du récepteur.

Exercice 2 : Transferts TCP

Le protocole TCP utilise des paquets appelés "segments" pour effectuer des communications de façon fiable en mode connecté. Cela signifie qu’une application utilisant TCP donne l’assurance que tous les segments envoyés sont reçus et que ces segments sont reçus dans le bon ordre.



Cet exercice reprend l’exercice précédent en utilisant le protocole TCP.

Exercice 3 : Dialogue avec un serveur existant

On souhaite réaliser un petit navigateur web (très simplifié) en mode texte. Pour ce faire, vous allez réaliser en ruby un client TCP. Ce client devra pouvoir se connecter en TCP sur le serveur web dont le nom (e.g. www.google.fr) sera passé sur la ligne de commande au lancement du programme. Une fois connecté, votre programme devra récupérer et afficher dans le terminal la page web qui aura été spécifiée sur la ligne de commande (e.g. index.html). On rappelle que les échanges de page web se font à l’aide du protocole HTTP (pour Hyper Text Transfer Protocol). Le port de communication par défaut d’un serveur web est le port numéro 80. La spécification du protocole HTTP se trouve dans le RFC (Request For Comments) 2068. Ce RFC est disponible à l’adresse suivante : Votre client ne devra supporter que la commande GET du protocole HTTP. La commande telnet m p établie une connexion TCP sur le port p de la machine m permettant alors de tester le protocole HTTP.

Exercice 4 : Talk multi-utilisateurs

On souhaite réaliser un système client/serveur permettant de communiquer à plusieurs simultanément sur le réseau. Le programme client devra au préalable se connecter au serveur, puis récupérer les chaînes de caractère entrées par l’utilisateur sur l’entrée standard et les envoyer au serveur. A la réception d’une chaîne de caractère, le serveur doit prendre en charge l’envoi de cette chaîne à tous les clients connectés au serveur, sauf au client dont la chaîne est originaire. L’implémentation se fera à l’aide du protocole TCP.

Exercices :

  • Reprenez les fichiers de l’exercice 2, ils vont vous servir de base pour la création d’un client / serveur TCP.
  • Le serveur va devoir écouter sur plusieurs sockets à la fois (une socket par client). Modifiez le programme de l’exercice 2 pour gérer la connexions de multiples clients. Il faut notamment définir une structure pour stocker les informations relatives à un client: paramètres réseaux et socket.
  • Maintenant que le serveur accepte de multiples clients, il faut également qu’il puisse écouter simultanément sur les différentes sockets associées aux clients. Pour cela nous allons utiliser la fonction select de manière à ce que le serveur écoute simultanément sur les différentes sockets associées aux clients.
  • Pour finaliser le serveur, ajoutez le traitement que ce dernier doit réaliser lorsqu’il reçoit un message d’un des clients. Cela signifie que lorsque la fonction select se débloque, vous devez identifier quel client a envoyé un message, récupérer ce message et l’envoyer aux autres clients.

Nous allons maintenant nous intéresser au client:

  • Un client doit gérer deux événements : la réception d’un message du serveur et son affichage sur l’écran, et la réception d’un message tapé par l’utilisateur sur la ligne de commande et son envoi au serveur. Ces deux événements doivent être gérés simultanément, nous allons donc utiliser la fonction select de manière à ce que le client écoute simultanément sur sa socket de communication avec le serveur et sur l’entrée standard.
  • Pour finaliser le client, ajoutez le traitement que ce dernier doit réaliser lorsqu’il reçoit un événement. Cela signifie que lorsque la fonction select se débloque, vous devez identifier si le client a reçu un message du serveur et dans ce cas l’afficher, ou si l’utilisateur a entré une chaîne de caractères et dans ce cas l’envoyer au serveur.
  • Lancez un serveur et plusieurs clients et vérifiez qu’un message envoyé par un client est bien reçu par les autres clients connectés au serveur.


389