Maison > Article > développement back-end > Utilisation du module asynchrone asyncore en Python et implémentation de httpclient
asyncore est un package de socket asynchrone, en particulier la classe dispatcher contient de nombreuses méthodes d'opération de socket pour les appels asynchrones, ce qui est très précis. Expliquons l'utilisation du module asynchrone asyncore en Python et l'implémentation de l'exemple httpclient
Bases
Ce module est une implémentation asynchrone de socket. Commençons par nous familiariser avec quelques classes et méthodes du module :
1.asyncore.loop
2.asyncore.dispatcher
La classe dispatcher est un objet wrapper de la classe socket sous-jacente. Pour le rendre plus utile, il dispose de méthodes de gestion d'événements qui sont appelées de manière asynchrone dans une boucle. Sinon, il s’agit d’un objet socket standard non bloquant.Les événements de bas niveau indiquent à la boucle asynchrone que certains événements de haut niveau se sont produits lors d'événements spécifiques ou d'états de connexion spécifiques. Par exemple, nous demandons à un socket de se connecter à un autre hôte.
(2) L'événement de lecture handle_close() n'a aucune donnée disponible.
(3) l'événement handle_accept read écoute une socket.
(4) handle_read
def handle_write(self): sent = self.send(self.buffer) self.buffer = self.buffer[sent:](6) handle_expt lorsqu'il y a une connexion de prise de données (OOB). Cela n'arrive presque jamais, car OOB est mal pris en charge et rarement utilisé. (7) handle_connectAppelé lorsque le socket crée une connexion. (8) handle_closeAppelé lorsque la connexion socket est fermée. (9) handle_errorAppelé lorsqu'une exception est levée et qu'il n'y a aucun autre traitement. (10) handle_acceptAppelé lorsque le canal d'écoute local établit une connexion avec l'extrémité distante (connexion passive). (11) readable est appelé à chaque fois dans la boucle asynchrone pour déterminer s'il faut ajouter un socket de canal à la liste des événements de lecture. La valeur par défaut est True. (12) writable Appelé à chaque fois dans la boucle asynchrone pour déterminer s'il faut ajouter un socket de canal à la liste des événements d'écriture, la valeur par défaut est True. (13) create_socket est le même que lors de la création d'un socket standard. (14) connect est le même que le paramètre de port du socket standard. Il accepte un tuple dont le premier paramètre est l'adresse de l'hôte et le deuxième paramètre est le numéro de port. (15) envoyerEnvoyer des données à la prise distante. (16) recvLire les données jusqu'à buffer_size à partir du socket distant. Une chaîne vide signifie que le canal est fermé à l'autre extrémité. (17) écouterÉcouter la connexion de la prise. (18)bindLier le socket à l'adresse. (19) accepterPour accepter une connexion, elle doit être liée à une socket et à une adresse d'écoute. (20) fermerFermez la prise.
3.asyncore.dispatcher_with_send
La sous-classe du répartiteur ajoute une simple fonction de sortie tampon pour les clients simples, et les plus complexes utilisent asynchat.async_chat.4.asyncore.file_dispatcher
file_dispatcher prend un descripteur de fichier ou une carte d'objet de fichier et un argument facultatif, wrapper, en utilisant la fonction Survey() ou Loop(). Si un objet fichier ou une méthode fileno() est fourni, cette méthode sera appelée et transmise au constructeur file_wrapper. Disponibilité : UNIX.5.asyncore.file_wrapper
file_wrapper prend un descripteur de fichier entier et appelle os.dup() pour copier le gestionnaire, afin que le gestionnaire d'origine puisse être fermé indépendamment de file_wrapper . Cette classe implémente suffisamment de méthodes pour simuler un socket à l'aide de la classe file_dispatcher. Disponibilité : UNIX.Instance asyncore
1. Implémentation d'un client http.
import socket import asyncore class Client(asyncore.dispatcher): def __init__(self, host, path): asyncore.dispatcher.__init__(self) self.create_socket(socket.AF_INET, socket.SOCK_STREAM) self.connect((host, 80)) self.buffer = 'GET %s HTTP/1.0\r\n\r\n' % path def handle_connect(self): pass def handle_close(self): self.close() def handle_read(self): print self.recv(8192) def writable(self): return (len(self.buffer) > 0) def handle_write(self): sent = self.send(self.buffer) self.buffer = self.buffer[sent:] client = Client('www.python.org', '/') asyncore.loop()Le serveur accepte les connexions et attribue des tâches
import socket import asyncore class EchoHandler(asyncore.dispatcher_with_send): def handle_read(self): data = self.recv(8192) if data: self.send(data) class EchoServer(asyncore.dispatcher): def __init__(self, host, port): asyncore.dispatcher.__init__(self) self.create_socket(socket.AF_INET, socket.SOCK_STREAM) self.set_reuse_add() self.bind((host, port)) self.listen(5) def handle_accept(self): pair = self.accept() if pair is not None: sock, addr = pair print 'Incoming connection from %s' % repr(addr) handler = EchoHandler(sock) server = EchoServer('localhost', 8080) asyncore.loop()
2. Utiliser le mappage de port d'asyncore (redirection de port)
import socket,asyncore class forwarder(asyncore.dispatcher): def __init__(self, ip, port, remoteip,remoteport,backlog=5): asyncore.dispatcher.__init__(self) self.remoteip=remoteip self.remoteport=remoteport self.create_socket(socket.AF_INET,socket.SOCK_STREAM) self.set_reuse_addr() self.bind((ip,port)) self.listen(backlog) def handle_accept(self): conn, addr = self.accept() # print '--- Connect --- ' sender(receiver(conn),self.remoteip,self.remoteport) class receiver(asyncore.dispatcher): def __init__(self,conn): asyncore.dispatcher.__init__(self,conn) self.from_remote_buffer='' self.to_remote_buffer='' self.sender=None def handle_connect(self): pass def handle_read(self): read = self.recv(4096) # print '%04i -->'%len(read) self.from_remote_buffer += read def writable(self): return (len(self.to_remote_buffer) > 0) def handle_write(self): sent = self.send(self.to_remote_buffer) # print '%04i <--'%sent self.to_remote_buffer = self.to_remote_buffer[sent:] def handle_close(self): self.close() if self.sender: self.sender.close() class sender(asyncore.dispatcher): def __init__(self, receiver, remoteaddr,remoteport): asyncore.dispatcher.__init__(self) self.receiver=receiver receiver.sender=self self.create_socket(socket.AF_INET, socket.SOCK_STREAM) self.connect((remoteaddr, remoteport)) def handle_connect(self): pass def handle_read(self): read = self.recv(4096) # print '<-- %04i'%len(read) self.receiver.to_remote_buffer += read def writable(self): return (len(self.receiver.from_remote_buffer) > 0) def handle_write(self): sent = self.send(self.receiver.from_remote_buffer) # print '--> %04i'%sent self.receiver.from_remote_buffer = self.receiver.from_remote_buffer[sent:] def handle_close(self): self.close() self.receiver.close() if __name__=='__main__': import optparse parser = optparse.OptionParser() parser.add_option( '-l','--local-ip', dest='local_ip',default='127.0.0.1', help='Local IP address to bind to') parser.add_option( '-p','--local-port', type='int',dest='local_port',default=80, help='Local port to bind to') parser.add_option( '-r','--remote-ip',dest='remote_ip', help='Local IP address to bind to') parser.add_option( '-P','--remote-port', type='int',dest='remote_port',default=80, help='Remote port to bind to') options, args = parser.parse_args() forwarder(options.local_ip,options.local_port,options.remote_ip,options.remote_port) asyncore.loop()En savoir plus sur le module asynchrone asyncore en Python Pour les articles liés à l'utilisation et à la mise en œuvre de httpclient, veuillez faire attention au site Web PHP chinois !