twisted reactor分析

Posted on 2018-02-27 23:07  王将军之武库  阅读(285)  评论(0编辑  收藏  举报

调用reactor.run(),就会调用到mainloop函数,从而调用到select或epoll,监控fd的读写。

posixbase.py:

    def listenTCP(self, port, factory, backlog=50, interface=''):
        p = tcp.Port(port, factory, backlog, interface, self)
        p.startListening()#会调用self.startReading(),再调用self.reactor.addReader(self)
#把自己加入epoll
return p def connectTCP(self, host, port, factory, timeout=30, bindAddress=None): c = tcp.Connector(host, port, factory, timeout, bindAddress, self) c.connect() return c

 factory类负责connect的管理,比如connect的建立、丢失、失败等,procotol是负责数据的接收。

 tcp.Connector(host, port, factory, timeout, bindAddress, self)

Connector类有factory,由factory可以找出procotol协议,协议主要是指tcp、process、ssl等。
class ClientCreator:
    """
    Client connections that do not require a factory.

    The various connect* methods create a protocol instance using the given
    protocol class and arguments, and connect it, returning a Deferred of the
    resulting protocol instance.

    Useful for cases when we don't really need a factory.  Mainly this
    is when there is no shared state between protocol instances, and no need
    to reconnect.

    The C{connectTCP}, C{connectUNIX}, and C{connectSSL} methods each return a
    L{Deferred} which will fire with an instance of the protocol class passed to
    L{ClientCreator.__init__}.  These Deferred can be cancelled to abort the
    connection attempt (in a very unlikely case, cancelling the Deferred may not
    prevent the protocol from being instantiated and connected to a transport;
    if this happens, it will be disconnected immediately afterwards and the
    Deferred will still errback with L{CancelledError}).
    """

    def __init__(self, reactor, protocolClass, *args, **kwargs):
        self.reactor = reactor
        self.protocolClass = protocolClass
        self.args = args
        self.kwargs = kwargs


    def _connect(self, method, *args, **kwargs):
        """
        Initiate a connection attempt.

        @param method: A callable which will actually start the connection
            attempt.  For example, C{reactor.connectTCP}.

        @param *args: Positional arguments to pass to C{method}, excluding the
            factory.

        @param **kwargs: Keyword arguments to pass to C{method}.

        @return: A L{Deferred} which fires with an instance of the protocol
            class passed to this L{ClientCreator}'s initializer or fails if the
            connection cannot be set up for some reason.
        """
        def cancelConnect(deferred):
            connector.disconnect()
            if f.pending is not None:
                f.pending.cancel()
        d = defer.Deferred(cancelConnect)#会生成一个延迟对象
        f = _InstanceFactory(
            self.reactor, self.protocolClass(*self.args, **self.kwargs), d)
        connector = method(factory=f, *args, **kwargs)
        return d


    def connectTCP(self, host, port, timeout=30, bindAddress=None):
        """
        Connect to a TCP server.

        The parameters are all the same as to L{IReactorTCP.connectTCP} except
        that the factory parameter is omitted.

        @return: A L{Deferred} which fires with an instance of the protocol
            class passed to this L{ClientCreator}'s initializer or fails if the
            connection cannot be set up for some reason.
        """
        return self._connect(
            self.reactor.connectTCP, host, port, timeout=timeout,
            bindAddress=bindAddress)#返回一个延迟对象

class BaseConnector:
    """Basic implementation of connector.

    State can be: "connecting", "connected", "disconnected"
    """
    timeoutID = None
    factoryStarted = 0

    def __init__(self, factory, timeout, reactor):
        self.state = "disconnected"
        self.reactor = reactor
        self.factory = factory
        self.timeout = timeout

    def disconnect(self):
        """Disconnect whatever our state is."""
        if self.state == 'connecting':
            self.stopConnecting()
        elif self.state == 'connected':
            self.transport.loseConnection()

    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()#创建一个client端
        if self.timeout is not None:
            self.timeoutID = self.reactor.callLater(self.timeout, transport.failIfNotConnected, error.TimeoutError())
        self.factory.startedConnecting(self)

重要结论:调用

Copyright © 2024 王将军之武库
Powered by .NET 9.0 on Kubernetes