The usage of asyncore asynchronous module in Python and the instance for implementing httpclient, asyncorehttpclient
Basic
This module is the asynchronous Implementation of socket. Let's familiarize ourselves with some classes and methods in this module:
1. asyncore. loop
Enter a round robin until the channel is closed by counting or opening.
2. asyncore. dispatcher
The dispatcher class is a packaging object of the underlying socket class. To make it more useful, some event processing methods are called asynchronously and cyclically. Otherwise, it is a standard non-blocking socket object.
Underlying events tell asynchronous loops in specific events or connection states that some advanced events occur. For example, we require a socket to connect to another host.
(1) handle_connect () The first read or write event.
(2) The handle_close () read event has no data available.
(3) The handle_accept read event listens to a socket.
(4) handle_read
It is called when an Asynchronous Loop detects a channel call for read.
(5) handle_write
It is called when the Asynchronous Loop detects that a writable socket can be written. This method often achieves Buffer Performance. For example
def handle_write(self): sent = self.send(self.buffer) self.buffer = self.buffer[sent:]
(6) handle_expt
When there is a (OOB) Data socket connection. This will almost never happen because OOB is fine-grained and rarely used.
(7) handle_connect
It is called when the socket creates a connection.
(8) handle_close
It is called when the socket connection is closed.
(9) handle_error
It is called when an exception is thrown and no other processing is performed.
(10) handle_accept
It is called when the local listening channel establishes a connection (passive connection) with the remote end.
(11) readable
It is called every time the Asynchronous Loop determines whether to add a channel socket to the read event list. The default value is True.
(12) writable
It is called every time the Asynchronous Loop determines whether to add a channel socket to the write event list. The default value is True.
(13) create_socket
It is the same as creating a standard socket.
(14) connect
The port setting is the same as that of the standard socket. The first parameter of a tuples is the host address, and the second parameter is the port number.
(15) send
Send data to remote socket.
(16) recv
Reads buffer_size data at most from a remote socket. An empty string means that the channel from the other end has been closed.
(17) listen
Listen for socket connections.
(18) bind
Bind the socket to the address.
(19) accept
To accept a connection, you must bind it to a socket and a listening address.
(20) close
Disable socket.
3. asyncore. dispatcher_with_send
The dispatcher sub-class adds a simple buffer output function for simple customers. It is more complex to use asynchat. async_chat.
4. asyncore. file_dispatcher
File_dispatcher requires a file descriptor or file object map, as well as an optional parameter, packaging, using investigation () or cyclic () functions. If a file object or any fileno () method is provided, this method is called and passed to the file_wrapper constructor. Availability: UNIX.
5. asyncore. file_wrapper
File_wrapper needs an integer file descriptor and calls OS. dup () for replication. This way, the original processing may be disabled independently of file_wrapper. This class implements enough methods to simulate a socket using the file_dispatcher class. Availability: UNIX.
Asyncore instance
1. Implement an http client.
import socketimport asyncoreclass 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()
The server accepts connections and assigns tasks.
import socketimport asyncoreclass 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. Use asyncore port ing (port forwarding)
import socket,asyncoreclass 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()