>  기사  >  백엔드 개발  >  Python에서 asyncore 비동기 모듈 사용 및 httpclient 구현

Python에서 asyncore 비동기 모듈 사용 및 httpclient 구현

高洛峰
高洛峰원래의
2017-03-01 14:20:012033검색

asyncore는 비동기 소켓 패키지입니다. 특히 디스패처 클래스에는 비동기 호출을 위한 많은 소켓 작업 메서드가 포함되어 있어 Python에서 asyncore 비동기 모듈의 사용법과 httpclient 예제의 구현을 설명하겠습니다.

기본
이 모듈은 소켓의 비동기 구현입니다. 먼저 모듈의 일부 클래스와 메서드에 대해 알아 보겠습니다.
1.asyncore.loop

패스 카운트 또는 공개 채널이 닫힐 때까지 폴링 루프에 들어갑니다.

2.asyncore.dispatcher

디스패처 클래스는 기본 소켓 클래스의 래퍼 개체입니다. 더 유용하게 만들기 위해 루프에서 비동기적으로 호출되는 일부 이벤트 처리 메서드가 있습니다. 그렇지 않으면 표준 비차단 소켓 개체입니다.
하위 수준 이벤트는 특정 이벤트 또는 특정 연결 상태에서 특정 상위 수준 이벤트가 발생했음을 비동기 루프에 알립니다. 예를 들어 소켓에 다른 호스트에 연결하도록 요청합니다.

(1) handler_connect() 첫 번째 읽기 또는 쓰기 이벤트입니다.
(2) handler_close() 읽기 이벤트에 사용할 수 있는 데이터가 없습니다.
(3) handler_accept 읽기 이벤트는 소켓을 수신합니다.
(4) handler_read

는 채널이 read()를 호출하는 것을 비동기 루프가 감지하면 호출됩니다.

(5) handler_write

는 비동기 루프가 쓰기 가능한 소켓에 쓸 수 있음을 감지하면 호출됩니다. 이 접근 방식은 종종 버퍼링 성능을 달성합니다. 예를 들어 (OOB) 데이터 소켓 연결이 있는 경우

def handle_write(self):
  sent = self.send(self.buffer)
  self.buffer = self.buffer[sent:]

(6) handler_expt

입니다. OOB는 제대로 지원되지 않고 거의 사용되지 않기 때문에 이런 일은 거의 발생하지 않습니다.

(7) handler_connect

소켓이 연결을 생성할 때 호출됩니다.

(8) handler_close

소켓 연결이 닫힐 때 호출됩니다.

(9) handler_error

예외가 발생하고 다른 처리가 없을 때 호출됩니다.

(10) handler_accept

로컬 청취 채널이 원격 측과 연결(수동 연결)을 설정할 때 호출됩니다.

(11) 읽기 가능

은 읽기 이벤트 목록에 채널 소켓을 추가할지 여부를 결정하기 위해 비동기 루프에서 매번 호출됩니다.

(12) 쓰기 가능

쓰기 이벤트 목록에 채널 소켓을 추가할지 여부를 결정하기 위해 비동기 루프에서 매번 호출되며 기본값은 True입니다.

(13) create_socket

은 표준 소켓을 생성할 때와 동일합니다.

(14) connect

는 표준 소켓의 포트 설정과 동일하며 첫 번째 매개변수가 호스트 주소이고 두 번째 매개변수가 포트 번호인 튜플을 허용합니다.

(15) send

원격 소켓으로 데이터를 보냅니다.

(16) recv

원격 소켓에서 최대 buffer_size 데이터를 읽습니다. 빈 문자열은 채널이 다른 쪽 끝에서 닫혀 있음을 의미합니다.

(17) 듣기

소켓 연결을 듣습니다.

(18)bind

소켓을 주소에 바인딩합니다.

(19) 수락

연결을 수락하려면 소켓과 수신 주소에 바인딩되어야 합니다.

(20) 닫기

소켓을 닫습니다.

3.asyncore.dispatcher_with_send

디스패처 하위 클래스는 간단한 클라이언트를 위한 간단한 버퍼 출력 기능을 추가하고 더 복잡한 클라이언트는 asynchat.async_chat을 사용합니다.

4.asyncore.file_dispatcher

file_dispatcher는 Survey() 또는 loop() 함수를 사용하여 파일 설명자 또는 파일 개체 맵과 선택적 인수인 래퍼를 사용합니다. 파일 객체나 fileno() 메서드가 제공되면 해당 메서드가 호출되어 file_wrapper 생성자에 전달됩니다. 가용성: UNIX.

5.asyncore.file_wrapper

file_wrapper는 정수 파일 설명자를 취하고 os.dup()을 호출하여 핸들러를 복사하므로 원래 핸들러는 독립적으로 닫힐 수 있습니다. file_wrapper . 이 클래스는 file_dispatcher 클래스를 사용하여 소켓을 시뮬레이션하는 데 충분한 메서드를 구현합니다. 가용성: UNIX.

asyncore 인스턴스

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

서버가 연결을 수락하고 작업을 할당합니다

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

Python에서 asyncore 비동기 모듈 사용과 관련된 추가 기사 및 httpclient 구현 PHP 중국어 웹사이트를 주목해주세요!


성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.