# module standard python de gestion des communications
import socket
# module d'encodage des objets python
import pickle

class ComSockSrv():
    '''Classe de base de gestion des communications, côté serveur.
    Reçoit les données des clients, les décode, les traite,
    et renvoie les résultats après encodage.
    Pour l'utilisation, dériver cette classe et surclasser la méthode "traiteMsg"
    (voir le programme exemple serveur.py).'''

    def run(self):
        '''Méthode à lancer pour recevoir et traiter les messages en boucle.'''

        # le host n'est pas renseigné sur le serveur, qui ne fait que répondre
        host = ''
        # le port est au choix ; il doit être identique à celui du client
        port = 8000
        # créee socket IP
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # options pour, entre autre, réutiliser le socket après un plantage
        sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        # attache le socket au bon port
        sock.bind((host,port))
        # permet de reprendre la main tous les dixièmes de seconde
        sock.settimeout(.1)

        # boucle perpétuelle (en l'état, le script peut être interrompu par ctrl-c)
        while True:
            # attend qu'un message soit disponible
            sock.listen(5)
            #
            try:
                # reçoit ce message. 1024 est la taille du buffer
                # (la taille totale de l'objet transmis peut être supérieure).
                conn, addr = sock.accept()
                msg = conn.recv(1024)
                # convertit le message reçu (un bloc de type byte) en objet python
                # data peut être n'importe quel object python envoyé par le client
                # (chaîne, liste, dictionnaire, etc)
                data = pickle.loads(msg)
                # appelle la méthode qui doit être surchargée pour permettre un traitement
                # (voir serveur.py). reponse est un objet python de n'importe quel type,
                # pas forcément le même que l'objet reçu.
                reponse = self.traiteMsg(data)
                # encode et renvoie l'objet issu du traitement
                conn.send(pickle.dumps(reponse))
                # ferme réception
                conn.close()
            # time out ?
            except socket.timeout:
                # ignoré, on va recommencer
                pass
            # on peut ici insérer un court traitement supplémentaire

    def traiteMsg(self,objet):
        '''Méthode à surclasser pour traiter les objets reçus (voir serveur.py)'''

        # par défaut, se contente de renvoyer 'ok'
        return 'ok'
