Maison >développement back-end >Tutoriel Python >Expliquer comment le module SocketServer en Python gère les requêtes réseau
SocketServer crée un cadre de service réseau. Il définit des classes pour gérer les requêtes réseau synchrones sur les flux TCP, UDP, UNIX et les datagrammes UNIX.
1. Types de serveurs
Il existe cinq classes de serveurs différentes dans SocketServer.
1.BaseServer définit l'API, et il n'est pas utilisé pour l'instanciation et l'utilisation directe.
2.TCPServer est utilisé pour la communication par socket TCP/IP.
3.UDPServer utilise des sockets datagramme.
4.UnixStreamServer et UnixDatagramServer utilisent des sockets de domaine Unix et sont utilisés intelligemment sur les plates-formes Unix.
2. Objets serveur
Créez un serveur via lequel l'adresse demandée et la classe de traitement des demandes (pas l'instance) peuvent être surveillées.
1.class SocketServer.BaseServer
Il s'agit de la super classe de tous les objets serveur du module. Elle définit l'interface et la majeure partie de l'implémentation est effectuée dans des sous-classes.
2.BaseServer.fileno
Renvoie un descripteur de fichier entier pour indiquer quel serveur écoute. Cette fonction est le plus souvent transmise à select.select(), permettant à plusieurs services de surveiller le même processus.
3.BaseServer.handle_request
Pour gérer une seule requête, cette fonction appellera les méthodes suivantes de manière séquentielle. get_request(), verify_request et process_request.
L'utilisateur fournit la méthode handle() et lève une exception, puis la méthode handle_error() sera appelée.
Si aucune demande n'est reçue dans self.timeout, handle_timeout() et handle_request() seront renvoyés.
4.BaseServer.serve_forever
BaseServer.serve_forever(poll_interval=0.5), traite la requête jusqu'à la requête explicite shutdown(). L'entraînement en rotation est clôturé à chaque fois poll_interval. Ignorez self.timeout. Si vous devez utiliser des tâches planifiées, vous devez utiliser d'autres threads.
5.BaseServer.shutdown
indique à serve_forever() d'arrêter la boucle.
6.BaseServer.RequestHandlerClass
Classe de gestionnaire de requêtes utilisateur, créez une instance de cette classe pour chaque requête.
3. Implémentation d'un serveur
Si vous créez un serveur, il peut généralement réutiliser les classes existantes et simplement fournir une classe de gestion des requêtes personnalisée. Il existe plusieurs méthodes BaseServer pour remplacer une sous-classe si cela ne répond pas à vos besoins.
1.verify_request(reqeust, client_address) : doit renvoyer une valeur booléenne. Si True est renvoyé, la demande sera traitée. Si False est renvoyée, la demande sera rejetée. Cette fonction peut être remplacée pour implémenter des services de contrôle d'accès.
2.process_request(request, client_address) : Appelez finish_request pour créer une instance de RequestHandlerClass() Si nécessaire, cette fonction peut créer un nouveau processus ou coroutine pour gérer la requête.
3.finish_request(request, client_address) : Créez une instance de traitement de requête. Appelez handle() pour gérer la requête.
4. Gestionnaires de requêtes
Les gestionnaires de requêtes effectuent l'essentiel du travail pour recevoir les demandes entrantes et décider des mesures à prendre. Le gestionnaire est responsable de l'implémentation de la couche socket sur le « protocole » (par exemple, HTTP ou XML-RPC). Lit les données de requête du gestionnaire de requêtes entrantes, les traite et écrit une réponse. Il existe trois façons de contourner cela.
1.setup() : prépare le gestionnaire de requêtes pour la requête, qui est initialisée et exécutée avant le handle.
2.handle() : effectuez le vrai travail de requête. Analysez les demandes entrantes, traitez les données et renvoyez les réponses.
3.finish() : Nettoyez le setup() créé à tout moment.
5. Exemples
L'exemple suivant montre TCP, UDP et asynchrone
1.Exemple de serveur TCP
import SocketServer class MyHandler(SocketServer.BaseRequestHandler): def handle(self): self.data = self.request.recv(1024).strip() print '{} wrote:'.format(self.client_address[0]) print self.data self.request.sendall(self.data.upper()) if __name__ == '__main__': HOST, PORT = 'localhost', 9999 server = SocketServer.TCPServer((HOST, PORT), MyHandler) server.serve_forever()
2 Exemple UDPServr
import SocketServer class MyHandler(SocketServer.BaseRequestHandler): def handle(self): data = self.request[0].strip() socket = self.request[1] print '{} wrote:'.format(self.client_address[0]) print data socket.sendto(data.upper(), self.client_address) if __name__ == '__main__': HOST, PORT = 'localhost', 9999 server = SocketServer.UDPServer((HOST, PORT), MyHandler) server.serve_forever()
3. Exemples asynchrones
Des gestionnaires asynchrones peuvent être construits via les classes ThreadingMixIn et ForkingMixIn.import socket import threading import SocketServer class MyHandler(SocketServer.BaseRequestHandler): def handle(self): data = self.request.recv(1024) curr_thread = threading.current_thread() response = '{}: {}'.format(curr_thread.name, data) self.request.sendall(response) class Server(SocketServer.ThreadingMixIn, SocketServer.TCPServer): pass def client(ip, port, message): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((ip, port)) try: sock.sendall(message) response = sock.recv(1024) print 'Received: {}'.format(response) finally: sock.close() if __name__ == '__main__': HOST, PORT = 'localhost', 0 server = Server((HOST, PORT), MyHandler) ip, port = server.server_address serer_thread = threading.Thread(target=server.serve_forever) server_thread.daemon = True server_thread.start() print 'Server loop running in thread:', server_thread.name client(ip, port, 'Hello World 1') client(ip, port, 'Hello World 2') client(ip, port, 'Hello World 3') server.shutdown() server.server_close()
4. SocketServer réalise une communication non bloquante entre le client et le serveur
(1. ) Créer un serveur SocketServerTCP
#创建SocketServerTCP服务器: import SocketServer from SocketServer import StreamRequestHandler as SRH from time import ctime host = 'xxx.xxx.xxx.xxx' port = 9999 addr = (host,port) class Servers(SRH): def handle(self): print 'got connection from ',self.client_address self.wfile.write('connection %s:%s at %s succeed!' % (host,port,ctime())) while True: data = self.request.recv(1024) if not data: break print data print "RECV from ", self.client_address[0] self.request.send(data) print 'server is running....' server = SocketServer.ThreadingTCPServer(addr,Servers) server.serve_forever()
from socket import * host = 'xxx.xxx.xxx.xxx' port = 9999 bufsize = 1024 addr = (host,port) client = socket(AF_INET,SOCK_STREAM) client.connect(addr) while True: data = raw_input() if not data or data=='exit': break client.send('%s\r\n' % data) data = client.recv(bufsize) if not data: break print data.strip() client.close()