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