Maison  >  Article  >  développement back-end  >  Expliquer comment le module SocketServer en Python gère les requêtes réseau

Expliquer comment le module SocketServer en Python gère les requêtes réseau

高洛峰
高洛峰original
2017-03-01 14:17:581826parcourir

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()


(2) Créer un client SocketServerTCP


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()


Pour plus d'explications sur la façon dont le module SocketServer en Python gère les requêtes réseau, veuillez prêter attention au site Web PHP chinois pour les articles connexes !

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn