Heim >Backend-Entwicklung >Python-Tutorial >Verwendung des asynchronen Moduls asynccore in Python und Implementierung von httpclient
Asyncore ist ein asynchrones Socket-Paket. Insbesondere enthält die Dispatcher-Klasse viele Socket-Operationsmethoden für asynchrone Aufrufe, was sehr scharfsinnig ist. Lassen Sie uns die Verwendung des asynchronen Moduls Asyncore in Python und die Implementierung des httpclient-Beispiels erklären
Grundlagen
Dieses Modul ist eine asynchrone Implementierung von Socket. Machen wir uns zunächst mit einigen Klassen und Methoden im Modul vertraut:
1.asyncore.loop
2.asyncore.dispatcher
Die Dispatcher-Klasse ist ein Wrapper-Objekt der zugrunde liegenden Socket-Klasse. Um es nützlicher zu machen, verfügt es über einige Methoden zur Ereignisbehandlung, die asynchron in einer Schleife aufgerufen werden. Ansonsten handelt es sich um ein standardmäßiges nicht blockierendes Socket-Objekt.Die Low-Level-Ereignisse teilen der asynchronen Schleife mit, dass bestimmte High-Level-Ereignisse bei bestimmten Ereignissen oder bestimmten Verbindungszuständen aufgetreten sind. Beispielsweise bitten wir einen Socket, eine Verbindung zu einem anderen Host herzustellen.
(2) Für das Leseereignis handle_close() sind keine Daten verfügbar.
(3) Das Leseereignis handle_accept lauscht auf einen Socket.
(4) handle_read
def handle_write(self): sent = self.send(self.buffer) self.buffer = self.buffer[sent:](6) handle_expt, wenn eine (OOB) Daten-Socket-Verbindung besteht. Dies passiert fast nie, da OOB schlecht unterstützt wird und selten verwendet wird. (7) handle_connectWird aufgerufen, wenn der Socket eine Verbindung herstellt. (8) handle_closeWird aufgerufen, wenn die Socket-Verbindung geschlossen wird. (9) handle_errorWird aufgerufen, wenn eine Ausnahme ausgelöst wird und keine andere Verarbeitung erfolgt. (10) handle_acceptWird aufgerufen, wenn der lokale Abhörkanal eine Verbindung mit dem entfernten Ende aufbaut (passive Verbindung). (11) readable wird jedes Mal in der asynchronen Schleife aufgerufen, um zu bestimmen, ob ein Kanal-Socket zur Leseereignisliste hinzugefügt werden soll. Der Standardwert ist True. (12) beschreibbar Wird jedes Mal in der asynchronen Schleife aufgerufen, um zu bestimmen, ob ein Kanal-Socket zur Schreibereignisliste hinzugefügt werden soll. Der Standardwert ist True. (13) create_socket ist dasselbe wie beim Erstellen eines Standard-Sockets. (14) connect entspricht der Porteinstellung des Standard-Sockets. Es akzeptiert ein Tupel, dessen erster Parameter die Hostadresse und der zweite Parameter die Portnummer ist. (15) sendenDaten an den Remote-Socket senden. (16) recvLiest bis zur Puffergröße Daten vom Remote-Socket. Eine leere Zeichenfolge bedeutet, dass der Kanal am anderen Ende geschlossen ist. (17) abhörenSocket-Verbindung abhören. (18)bindBinden Sie den Socket an die Adresse. (19) akzeptierenUm eine Verbindung zu akzeptieren, muss sie an einen Socket und eine Abhöradresse gebunden sein. (20) schließenSteckdose schließen.
3.asyncore.dispatcher_with_send
Die Dispatcher-Unterklasse fügt eine einfache gepufferte Ausgabefunktion für einfache Clients hinzu, und komplexere verwenden asynchat.async_chat.4.asyncore.file_dispatcher
file_dispatcher verwendet einen Dateideskriptor oder eine Dateiobjektzuordnung und ein optionales Argument, einen Wrapper, mithilfe der Funktion „survey()“ oder „loop()“. Wenn ein Dateiobjekt oder eine fileno()-Methode bereitgestellt wird, wird diese Methode aufgerufen und an den file_wrapper-Konstruktor übergeben. Verfügbarkeit: UNIX.5.asyncore.file_wrapper
file_wrapper nimmt einen ganzzahligen Dateideskriptor und ruft os.dup() auf, um den Handler zu kopieren, sodass der ursprüngliche Handler unabhängig geschlossen werden kann von file_wrapper . Diese Klasse implementiert genügend Methoden, um einen Socket mithilfe der Klasse file_dispatcher zu simulieren. Verfügbarkeit: UNIX.Asynccore-Instanz
1. Implementierung eines http-Clients.
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()Der Server nimmt Verbindungen an und weist Aufgaben zu
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. Verwenden Sie die Portzuordnung (Portweiterleitung) von Asyncore
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()Mehr über das Asyncore-Asynchronmodul in Python Für Artikel zur Verwendung und Implementierung von httpclient beachten Sie bitte die chinesische PHP-Website!