Langage Python:
Exemple de jeu en réseau: le morpion

Présentation du projet

Notion de réseau

Tout d'abord, nous allons voir comment établir une communication entre deux machines seulement. L'une et l'autre pourront s'échanger des messages à tour de rôle, mais l'une de ces machines jouera le rôle d'un logiciel serveur, alors que l'autre se comportera comme un logiciel client.

Le serveur

Le logiciel serveur fonctionne en continu, sur un ordinateur dont l'identité est définie sur le réseau grâce à une adresse IP. Il guette en permanence l'arrivée de requêtes expédiées par les clients potentiels en direction de cette adresse, par l'intermédiaire d'un port de communication bien déterminé. Pour ce faire, le script correspondant doit mettre en oeuvre un objet logiciel associé à ce port, que l'on appelle un socket ou connecteur réseau.

Pour savoir l'adresse IP de votre ordinateur, ouvrez une invite de commande MS-DOS (Windows) ou le Terminal (OSX) et taper: ipconfig /all (pour windows) ou ifconfig (pour OSX)

Le client

Au départ d'une autre machine, le logiciel client tente d'établir la connexion en émettant une requête appropriée. Cette requête est un message qui est confié au réseau, un peu comme on confie une lettre à la Poste. Le réseau pourrait en effet acheminer la requête vers n'importe quelle autre machine, mais une seule est visée : pour que la destination visée puisse être atteinte, la requête contient dans son en-tête l'indication de l'adresse IP et du port de communication destinataires.

Lorsque la connexion est établie avec le serveur, le client lui assigne lui-même l'un de ses propres ports de communication. A partir de ce moment, on peut considérer qu'un canal privilégié relie les deux machines, comme si on les avait connectées l'une à l'autre par l'intermédiaire d'un fil (les deux ports de communication respectifs jouant le rôle des deux extrémités de ce fil). L'échange d'informations proprement dit peut commencer.

Différents types de sockets

Les sockets peuvent mettre en oeuvre deux techniques de communication différentes et complémentaires:

Exemple: Création d'une communication

On commence par le logiciel serveur:
serveur


import socket
from tkinter import *
from tkinter.messagebox import *


def connexion():
    global connexion_avec_client, infos_connexion, connexion_principale

    connexion_principale = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    connexion_principale.bind((HOST.get(), PORT.get()))
    connexion_principale.listen(5)
    print("Le serveur écoute à présent sur le port {}".format(PORT.get()))
    connexion_avec_client, infos_connexion = connexion_principale.accept()
    dialogue()

def envoyer(message):
    message=message.encode()
    connexion_avec_client.send(message)

def recevoir():
    msg_recu = connexion_avec_client.recv(1024)
    msg_recu=msg_recu.decode()
    return msg_recu

def dialogue():
    while 1:
        msg_recu=recevoir()
        print(msg_recu)
        message = input("Entrez votre message: ")
        print(message)
        envoyer(message)

    print("Fermeture de la connexion")
    connexion_avec_client.close()
    connexion_principale.close()


# Création de la fenêtre principale (main window)
Mafenetre = Tk()

Mafenetre.title('Mise en réseau - Serveur')

# Cadre1 : paramètres serveur
cadre1 = Frame(Mafenetre,borderwidth=2,relief=GROOVE)
cadre1.grid(row=0,column=0,padx=5,pady=5,sticky=W+E)

Label(cadre1, text = "Hôte").grid(row=0,column=0,padx=5,pady=5,sticky=W)
HOST = StringVar()
HOST.set('127.0.0.1')
Entry(cadre1, textvariable= HOST).grid(row=0,column=1,padx=5,pady=5)

Label(cadre1, text = "Port").grid(row=1,column=0,padx=5,pady=5,sticky=W)
PORT = IntVar()
PORT.set(50026)
Entry(cadre1, textvariable= PORT).grid(row=1,column=1,padx=5,pady=5)

ButtonConnexion = Button(cadre1, text ='Ouvrir le serveur',command=connexion)
ButtonConnexion.grid(row=0,column=2,rowspan=2,padx=5,pady=5)




Mafenetre.mainloop()


Ensuite le logiciel client:


import socket
from tkinter import *
from tkinter.messagebox import *

def connexionserveur():
    global connexion_avec_serveur

    connexion_avec_serveur = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    connexion_avec_serveur.connect((HOST.get(), PORT.get()))
    print("Connexion établie avec le serveur sur le port {}".format(PORT.get()))
    dialogue()

def envoyer(message):
    message=message.encode()
    connexion_avec_serveur.send(message)

def recevoir():
    msg_recu = connexion_avec_serveur.recv(1024)
    msg_recu=msg_recu.decode()
    return msg_recu

def dialogue():
    while 1:
        message = input("Entrez votre message: ")
        print(message)
        envoyer(message)
        msg_recu=recevoir()
        print(msg_recu)

    print("Fermeture de la connexion")
    connexion_avec_serveur.close()


# Création de la fenêtre principale (main window)
Mafenetre = Tk()

Mafenetre.title('Mise en réseau - Client')

# Cadre1 : paramètres serveur
cadre1 = Frame(Mafenetre,borderwidth=2,relief=GROOVE)
cadre1.grid(row=0,column=0,padx=5,pady=5,sticky=W+E)

Label(cadre1, text = "Hôte").grid(row=0,column=0,padx=5,pady=5,sticky=W)
HOST = StringVar()
HOST.set('127.0.0.1')
Entry(cadre1, textvariable= HOST).grid(row=0,column=1,padx=5,pady=5)

Label(cadre1, text = "Port").grid(row=1,column=0,padx=5,pady=5,sticky=W)
PORT = IntVar()
PORT.set(50026)
Entry(cadre1, textvariable= PORT).grid(row=1,column=1,padx=5,pady=5)

ButtonConnexion = Button(cadre1, text ='Connexion au serveur',command=connexionserveur)
ButtonConnexion.grid(row=0,column=2,rowspan=2,padx=5,pady=5)




Mafenetre.mainloop()



Se mettre par deux, l'un lance le serveur en renseignant sa propre adresse IP et un port de son choix (entre 49152 et 65535). L'autre lance le client en renseignant l'adresse IP du serveur et le port choisi par le serveur.

Réalisation du projet


Partie 1: Une ébauche de morpion dans un sens: client vers serveur

Partie 2: La réponse du serveur
Associer aux boutons du logiciel serveur deux fonctions permettant de mettre en rouge les boutons du logiciel serveur ainsi que les boutons respectifs du logiciel client.

Partie 3: Généraliser aux neuf cases d'un morpion