Python in Reactor,factory,protocol

Source: Internet
Author: User

In the simplest case, in addition to understanding the simple use of reactor, you should also know about protocol and factory. They will eventually be dispatched by Reactor's listening setup and run.

The first problem to establish a server is the communication protocol between the service and the outside world. The definition of a protocol is implemented in twisted by inheriting the Twisted.internet.protocol.Protocol class. In the protocol you can define a series of events, such as connections, data reception, disconnection, and so on, if they respond. However, the creation of all connected protocols and the storage of persistent configuration data are not preserved in the protocol.

Storage of persistent configuration data is usually stored in the factory.

The definition of a factory is implemented in twisted by inheriting the Twisted.internet.protocol.Factory class. Twisted provides the most common requirements for the default factory implementation. It instantiates each protocol and, by setting the factory attribute in each protocol, allows the Protocol to be used by itself, and the purpose of this setting is to allow the protocol to use persistent configuration data stored in the factory for processing the connection data. The start-up of a factory requires reactor real-world listening and startup to be realized.
The establishment of reactor listening can be referred to Twisted.internet.interfaces.IReactorTCP.listenTCP. At this point we'll just talk about setting up a TCP server for listening, if you need other kinds of listening to establish reference ireactor*.listen* series API.

To summarize, we write a twisted daemon that essentially focuses on three levels of objects. They are configurable to each other and can be developed independently, and can only be used in conjunction with simple invocation configurations. The first level is the establishment of listening, the initialization of the factory, the operation of the server, it needs reactor development. The second level is the initialization of the service, the establishment of the user connection, the storage of persistent configuration data, and the instantiation of the Protocol, which requires factory development. The third level is the user connection after the establishment of event processing, which requires protocol development.

One

Protocol: The internal implementation of the main is connected in the communication of the action;

Internal transport, write (), Getpeer (Host,port)

and a factory.

Factory: To save the information of the connecting party, when there is a link, Factory will initialize a protocol to establish a connection with each other, so there is protocol in Factory. Because the protocol method often uses the attribute variables in the factory, there are factory in the Protocol class. There is a circular reference to the problem, in Python, some classes are garbage cleanup mechanism, but for those who have defined method __del__ () of the class, there will be a memory leak problem.

Reactor: Is the core of the management twisted Framework. All events trigger reactor, and then he starts the service, initializes the factory,factory, and initializes the protocol.

The basis of factory and protocol is implemented in the protocol.py file.

Two

Reactor:

is a very important concept in the twisted framework, event-driven. He is responsible for monitoring all events.

The most common is run (), Stop (), Calllater ()

Calllater () actually instantiates a delayedcall () class and returns the handle to the instance. You can perform operations such as cancel (), reset (), delay ().

The implementation of reactor should inherit the class Reactorbase (object) in the internet\base.py file as well as the class _signalreactormixin, where the _signalreactormixin class has a defined run ( function

Reactorbase (Object) class, there is a method stop (). Many reactor and thread operation functions can also be found here, the above Calllater () is implemented here.

In the internet\posixbase.py file, there is the class Posixreactorbase (_signalreactormixin, Reactorbase), which is the inheritance of the two classes mentioned above. Here, a variety of listen** functions are implemented, the main waiter server, and the corresponding connect** function for the client.

< a >, for example: The client can use: reactor. Connecttcp (self, host, port, factory, timeout=30, Bindaddress=none)

This is a direct can use, so reactor must inherit from Posixreactorbase.

In Connecttcp (), the implementation is as follows:

c = tcp. Connector (host, port, factory, timeout, bindaddress, self)

C.connect ()

Return C

The first sentence: instance of a TCP. The connector class, which inherits from base. Baseconnector;

Class base. Baseconnector is implemented in the following ways: Disconnect (), connect (), stopconnecting (self), canceltimeout (self), buildprotocol, Connectionfailed (self, Reason), connectionlost (self, reason) ...

These methods, like the methods in factory, function names are very similar, in fact, the inside of these functions is called the corresponding factory method. One of the most important variables in this class is self.factory.

The second sentence: is the initiator of the connection function, the main is to open the factory (Connecttcp function in the incoming).

Connect () is defined as follows:

def connect (self):

"" "Start connection to remote server." "" "

If self.state! = "Disconnected":

Raise RuntimeError, "can ' t connect in this State"

self.state = "Connecting"

If not self.factorystarted:

Self.factory.doStart ()

self.factorystarted = 1

Self.transport = transport = Self._maketransport ()

If Self.timeout is not None:

Self.timeoutid = Self.reactor.callLater (self.timeout, transport.failifnotconnected, error. Timeouterror ())

Self.factory.startedConnecting (self)

In the above analysis, reactor, factory, protocol is linked together, a lot of operation is clear. Go back to reading the most cited content, you should understand more.

< two >, for the service side: reactor. Listentcp (self, port, factory, Backlog=50, interface= ")

The specific implementation is as follows:

p = tcp. Port (port, factory, backlog, interface, self)

P.startlistening ()

Return P

The first sentence: instance of a TCP. Port class, which inherits base. Baseport, _socketcloser.

The methods implemented are:

Createinternetsocket (self), startlistening (self), _buildaddr (self, (host, Port)),

Doread (self), connectionlost (self, Reason), gethost (self), dowrite (self)

Loseconnection (self, conndone=failure. Failure (Main. Connection_done))

There are also self.factory variables

The second sentence: Do the necessary preparation, such as: Create and bind socket, listen port, read data and so on.

def startlistening (self):

"" "Create and bind my socket, and begin listening on it.

This was called on Unserialization, and must was called after creating a

Server to begin listening on the specified port.

"""

Try

Skt = Self.createinternetsocket ()

Skt.bind ((Self.interface, Self.port))

Except Socket.error, le:

Raise Cannotlistenerror, (Self.interface, Self.port, le)

# Make sure so if we listened on Port 0, we update this to

# reflect what the OS actually assigned us.

Self._realportnumber = Skt.getsockname () [1]

Log.msg ("%s starting on%s"% (self.factory.__class__, self._realportnumber))

# The order of the next 6 lines is kind of bizarre. If no One

# can explain it, perhaps we should re-arrange them.

Self.factory.doStart ()

Skt.listen (Self.backlog)

self.connected = True

Self.socket = Skt

Self.fileno = Self.socket.fileno

self.numberaccepts = 100

Self.startreading ()

Where Skt is the socket handle returned by Socket.socket ().

Third, continue in-depth:

The above is reactor.connecttcp (), this method will go directly to work (initialization factory,protocol, etc.), perhaps we need to manually control the process. The following is the use of classes to implement:

\appliction\internet.py file, class TcpClient, at that time, in order to find the class name, spent a lot of time, the class name is formed by combining.

The prototype is: Class _abstractclient (_volatiledataservice)

and the Class _abstractserver (_volatiledataservice) as the service-side prototype.

A few classes are a pattern of the above two classes:

TCPServer, TCPClient,

Unixserver, Unixclient,

Sslserver, Sslclient,

Udpserver, UdpClient,

Unixdatagramserver, Unixdatagramclient,

Multicastserver

The class _abstractclient and class _abstractserver are ultimately inherited from the server in \appliction\server.py. Two classes are services, just slightly different in the implementation process, one for connect, one for port.

They all have:

Self.reactor is passed in by parameters.

Self.method, the way to save the connection, such as TCP,UDP

Self._connection, Save the connection (actually the return value of the above listen** or connect**)

The object has been instantiated, how to start the service (work)? StartService (self)

1), first look at the class _abstractserver:

def startservice (self):

Service. Service.startservice (self)

If Self._port is None:

Self._port = Self._getport ()

def _getport (self):

"""

Wrapper around the appropriate listen method of the reactor.

@return: The Port object returned by the Listen method.

@rtype: An object providing L{ilisteningport}.

"""

If Self.reactor is None:

From twisted.internet Import reactor

Else

Eactor = Self.reactor

Return GetAttr (reactor, ' listen%s '% (Self.method,)) (

*self.args, **self.kwargs)

Getattr () This function is good, hehe

The final call is the linsten** in reactor, but it is defined by a server first and then opened by Server.startserver ().

2), then look at class _abstractclient

def startservice (self):

Service. Service.startservice (self)

Self._connection = Self._getconnection ()

def _getconnection (self):

"""

Wrapper around the appropriate connect method of the reactor.

@return: The Port object returned by the Connect method.

@rtype: An object providing L{iconnector}.

"""

If Self.reactor is None:

From twisted.internet Import reactor

Else

Reactor = Self.reactor

Return GetAttr (reactor, ' connect%s '% (Self.method,)) (

*self.args, **self.kwargs)

The reference above, very clear.

Python in Reactor,factory,protocol

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.