Python Asyncore asynchronous Socket module and example of port forwarding

Source: Internet
Author: User
The asyncore module is a encapsulated module for processing socket events and adopts asynchronous processing methods. here we will explain the Asyncore asynchronous Socket module of Python and the example for implementing port forwarding, for more information, see the Asyncore module, which provides the basic structure for writing data to the socket service client and server asynchronously.

There are only two ways for a program to "do more than one thing at the same time" on a single processor ". Multi-threaded programming is the simplest and most popular method, but there is another very different technology that can make us maintain almost all the advantages of multithreading, but do not really use multithreading. If your program is mainly restricted by I/O, this is the only feasible method. If your program is restricted by the processor, the preemptive scheduling thread may be what you really need. However, few network servers are limited by processors.

If your operating system supports select () system calls in its I/O library (almost all systems support), you can use it to process multiple communication channels at a time; when your I/O is busy in the background. Although this strategy seems strange and complicated, especially at the very beginning, it is easier to understand and control than multi-threaded programming in many aspects. The asyncore module solves many difficulties for you and enables you to quickly build complex high-performance network servers and clients. The asynchat module is very useful for session applications and protocols.

The idea behind the two modules is to create one or more network channels and asyncore. dispatcher and asynchat. instance of the async_chat class. if you do not provide your own ING, the creation channel adds the two instances to the global ing used by the loop () function.

Once the initialization channel is created, calling the loop () function will activate the channel service, which will continue until the last Channel (including all channels added to the ing in the asynchronous service) is closed.
The module file contains a loop () function and a dispatcher base class. The loop () function is a global function, which checks a dict that stores the dispatcher instance, also known as channel.
Every object that inherits the dispatcher class can be considered as a socket to be processed. Therefore, we only need to define a class that inherits the dispatcher, and then rewrite some methods, generally, the method starts with handle.

Port forwarding example
If your program wants to do one thing at a time, multithreading is the fastest and most common method, but there is another way, it is particularly useful when I/O traffic is high. If your operating system supports the select function, you can enable I/O to be read and written in the background. This module sounds complicated, but there are actually many ways to understand it. this document helps you solve these problems.
I think this module should be an event-driven asynchronous I/O, similar to the C ++ event selection model. Every time a read or write event occurs, it will be handled by the event function we rewrite.
Here is a script for writing port forwarding using the asyncore module. from this script, you can understand the basic usage of asyncore.
In this article, the client is our computer, and the server is the forwarded address. That is, the information sent from the client to this script, which is forwarded to the server.
First, define a forwarder class:

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)

This class inherits from the dispatcher class of the asyncore module (it is our main class, including some functions to be reloaded later). The constructor obtains five parameters, the 1st and 2 parameters are the local IP address and port of the script listener, and the 3rd and 4 parameters are the IP address and port of the server. The 5th parameters are the parameters of the listen function, and the maximum length of the waiting queue.
To use this class, you only need to create an object as follows, pass in the corresponding IP address and port, and then enter the loop:

forwarder(options.local_ip,options.local_port,options.remote_ip,options.remote_port)asyncore.loop()

After entering the loop, it is equivalent to enabling a daemon thread and running in the background, waiting for the occurrence of socket events.
Because this script is a port forwarding tool, the actual running process is: the client connects to the port of this script, so that the data script sent to this port is automatically forwarded to the server address and port. Therefore, the connection message (accept event) should be received first ).
Then, when the accept event occurs, it enters the handle_accept function. So we can see that the handle_accept function actually calls the accept function to receive the client connection object and address. A new sender class object is created. the object is defined as follows:

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'%sent    self.receiver.from_remote_buffer = self.receiver.from_remote_buffer[sent:]  def handle_close(self):    self.close()    self.receiver.close()

This class is also inherited from asyncore. dispatcher. its constructor receives three parameters: recv object (mentioned later), remote address, and corresponding port.
The function creates a new socket, which is the socket that communicates with the server port, and then calls connect to the port.
Later, we actually entered a process of waiting for messages. because we sent a connect, the next message we received should be connect, and handle_connect is a function that passes. No content is executed.
After the connection is complete, we have established a port forwarding channel. When the client sends a packet to the port listened by the script, it will automatically forward the packet to the server port. The data packet returned by the server port is automatically forwarded to the client.
Return to the 1st parameters of the constructor. we can see in the forwarder class function that a conn object is passed in, and the conn object is also a class. let's take a look at the definition of this class:

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

It also inherits asyncore. dispatcher. The constructor only receives one parameter, that is, the return value of connect, a connection object.
In fact, this object is the communication between listening, processing, and the client. the sender object mentioned previously is the communication between listening, processing, and the server.

The above is the content of the Asyncore asynchronous Socket module of Python and the example of implementing port forwarding. For more information, please follow the PHP Chinese network (www.php1.cn )!

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.