Heim  >  Artikel  >  Backend-Entwicklung  >  Verwendung des asynchronen Moduls asynccore in Python und Implementierung von httpclient

Verwendung des asynchronen Moduls asynccore in Python und Implementierung von httpclient

高洛峰
高洛峰Original
2017-03-01 14:20:012066Durchsuche

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

Betreten Sie eine Umfrageschleife, bis eine Passanzahl erreicht oder ein offener Kanal geschlossen wurde.

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.

(1) handle_connect() erstes Lese- oder Schreibereignis.

(2) Für das Leseereignis handle_close() sind keine Daten verfügbar.
(3) Das Leseereignis handle_accept lauscht auf einen Socket.
(4) handle_read

wird aufgerufen, wenn die asynchrone Schleife erkennt, dass der Kanal read() aufruft.

(5) handle_write

wird aufgerufen, wenn die asynchrone Schleife erkennt, dass ein beschreibbarer Socket geschrieben werden kann. Mit diesem Ansatz wird häufig eine Pufferleistung erzielt. Zum Beispiel

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_connect

Wird aufgerufen, wenn der Socket eine Verbindung herstellt.

(8) handle_close

Wird aufgerufen, wenn die Socket-Verbindung geschlossen wird.

(9) handle_error

Wird aufgerufen, wenn eine Ausnahme ausgelöst wird und keine andere Verarbeitung erfolgt.

(10) handle_accept

Wird 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) senden

Daten an den Remote-Socket senden.

(16) recv

Liest bis zur Puffergröße Daten vom Remote-Socket. Eine leere Zeichenfolge bedeutet, dass der Kanal am anderen Ende geschlossen ist.

(17) abhören

Socket-Verbindung abhören.

(18)bind

Binden Sie den Socket an die Adresse.

(19) akzeptieren

Um eine Verbindung zu akzeptieren, muss sie an einen Socket und eine Abhöradresse gebunden sein.

(20) schließen

Steckdose 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 &#39;%04i <--&#39;%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 &#39;<-- %04i&#39;%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 &#39;--> %04i&#39;%sent
    self.receiver.from_remote_buffer = self.receiver.from_remote_buffer[sent:]

  def handle_close(self):
    self.close()
    self.receiver.close()

if __name__==&#39;__main__&#39;:
  import optparse
  parser = optparse.OptionParser()

  parser.add_option(
    &#39;-l&#39;,&#39;--local-ip&#39;,
    dest=&#39;local_ip&#39;,default=&#39;127.0.0.1&#39;,
    help=&#39;Local IP address to bind to&#39;)
  parser.add_option(
    &#39;-p&#39;,&#39;--local-port&#39;,
    type=&#39;int&#39;,dest=&#39;local_port&#39;,default=80,
    help=&#39;Local port to bind to&#39;)
  parser.add_option(
    &#39;-r&#39;,&#39;--remote-ip&#39;,dest=&#39;remote_ip&#39;,
    help=&#39;Local IP address to bind to&#39;)
  parser.add_option(
    &#39;-P&#39;,&#39;--remote-port&#39;,
    type=&#39;int&#39;,dest=&#39;remote_port&#39;,default=80,
    help=&#39;Remote port to bind to&#39;)
  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!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn