#!/usr/bin/python # coding: utf-8 # C. Attiogbe, Université de Nantes # # Parmi les deux façons de realiser les serveurs de N clients, il y a # 1. Les Threads () # 2. Scrutation des evenements sur plusieurs sockets dédiés aux clients : avec SELECT # Nous donnons ici les grandes lignes de la solution 2 # La principale idée est donc de scruter les sockets # et de retourner à une appli principale, # la liste des sockets sur lesquels il y a des événements # Interface de la fonction select # readable_sockets, writable_sockets, error_sockets = select(read_socks , write_socks, except_socks [, timeout]); # Fonctionnement de la fonction select # readable_sockets : contient un sous-ens des sockets sur lesquels il y a des entrees/lectures # writable_sockets : contient le sous-ens des sockets qui ont des buffers non vides # error_sockets : contient le sous-ens de socks où il y a des exceptions # Trois cas sont encore possible sur les readable_sockets : # 1. si on a le sock initial du serveri, ==> il est pret à accepter des connexions # Les nouvelles connexions sont ajourées à la liste des read_socks ou input_socks # Une connexion établie avec un client qui envoie des donnees. # La donnee doit etre lue avec recv() et placee dans la queue pour etre renvoye au server/client # Un socket readable sans donnee est relatif a un client decnnecté # 2. S'il y a de la donnee dans la queue pour une connexion , le message suivant est envoyé. # 3. S'il y a une erreur sur un socket, il est fermé # # docs/reference ==> https://pymotw.com/2/select/ import socket, select if __name__ == "__main__": INPUT_SOCKS = [] # liste de sockets pour les # de la meme facon, on peut definir OUTPUT_SOCKs et ERR_SOCKS OUTPUT_SOCKS = [] ERR_SOCKS = [] RECV_BUFFER = 1024 # buffer de données PORT = 50007 # arbitrairement (en evitant les ports predefinis) HOST ='' MAXI=12 # seuil max client dans la queue d'ecoute server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) server_socket.bind((HOST, PORT)) #"0.0.0.0" server_socket.listen(MAXI) # ecoute INPUT_SOCKS = [server_socket] # ajout du socket du server dans la liste scruta # ou bien INPUT_SOCKS.append() server_socket) print "Serveur de clts multiples démarrés sur le port " + str(PORT) while 1: read_sockets,write_sockets,error_sockets = select.select(INPUT_SOCKS,OUTPUT_SOCKS, ERR_SOCKS) # recup la liste des sockets surlequels il y a xsdes activités en read, write, err for sock in read_sockets: # cas d'une nouvelle connexion sur le socket serveur if sock == server_socket: # nouvelle connexion reçue sur server_socket sockConn, addr = server_socket.accept() # accepte connex, addr= couple (adrIP, port) INPUT_SOCKS.append(sockConn) print "Client (%s, %s) connected" % addr #il y a un message venant d'un client else: # Data received from client, process traitement de donnee provenant d'un ct try: data = sock.recv(RECV_BUFFER) # retour de la donnee en echo if data: sock.send('SRV::' + data) # client peut etre deconnecté, l'effacer de la listex except: broadcast_data(sock, "Client (%s, %s) off" % addr) print "Client (%s, %s) is offline" % addr sock.close() INPUT_SOCKS.remove(sock) continue server_socket.close() #-------------------------------------------------